This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
wiki:epims4_0:developer:ep-core [2008/03/04 13:15] dupierris |
wiki:epims4_0:developer:ep-core [2009/01/21 16:41] (current) 132.168.73.9 |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== Guide d'implémentation d'eP-Core ====== | ====== Guide d'implémentation d'eP-Core ====== | ||
- | ===== Introduction ===== | ||
- | eP-Core est le module d'accès à la BD. Ce module permet d'obtenir les objets Java représentant les données de la BD ePims ainsi que les services permettant d'agir sur ces objets. | ||
- | Ce module est déployé de façon indépendante sur le serveur d'application Java Geronimo afin d'être utilisé et partagé par les autres modules de présentations et de service du système. | ||
- | |||
- | |||
- | ===== Technologies ===== | ||
- | {{ epimsarchigeneral.png }} | ||
- | ** Figure 1 Architecture globale de l’application** | ||
- | |||
- | Le schema représente la totalité de l'application ePims. eP-Core représentele noyau de cette application, il ne contient pas ce qui se rapporte à la couche présentation càd interfaces Web, il constitue le point d’accès aux données de l’application ainsi qu’aux actions sur ces données (création, modification, suppression) au travers d’interfaces accessibles par toutes les couches de l’application. | ||
- | |||
- | Comme indiqué sur ce schéma, les technologies utilisées dans l'application ePims sont les suivantes: | ||
- | |||
- | * Les JSP/JSF sont utilisés pour la partie présentation | ||
- | * Au niveau de la logique applicative, on utilise le framework Spring qui est un conteneur léger et qui permet, d’une part, d’isoler les différentes technologies utilisées et faciliter ainsi la substitution d’une implémentation par une autre, d’autre part, Spring prend en charge la partie transactionnelle de O/RM. | ||
- | * Hibernate a été choisi pour la partie O/R Mapping. Ce framework a, entre autres, l’avantage de s’interconnecter facilement avec Spring. | ||
- | |||
- | |||
- | ===== Structure du projet ===== | ||
- | ==== Les cibles Ant ==== | ||
- | Les cibles Ant principales définies pour eP-Core sont : | ||
- | |||
- | * configure.dist : Configure le projet pour une distribution de production (copie des fichiers de configutations, mise en place de librairies...) | ||
- | * compile.dist : compile les classes Java et appel __configure.dist__. | ||
- | * configure.test : Même configuration que précédement mais utilise les fichiers de configuration pour exécuter les tests JUnit.(appel de __configure.dist__) | ||
- | * compile.test : compile les classes Java et appel __configure.test__. | ||
- | * configure.dev : Même configuration que configure.dist mais utilise les fichiers de configuration pour le mode développement.(appel de __configure.dist__) | ||
- | * compile.dev : compile les classes Java et appel __configure.dev__. | ||
- | * dist : créer une distribution de ep-Core comme module geronimo ... appel toutes les cibles nécessaire à cette création | ||
- | * dist.dev : idem dist mais appel __compile.dev__ au lieu de compile.dist. | ||
- | * dev.create.onejar : Temporaire ! Créer un seul .jar contenant toutes les librairies (lib/*) ainsi que eP-Core.jar créer lors d'une execution de dist. N'appèle pas dist qui doit donc avoir été exécuté avant ! | ||
- | * publish.libs : a exécuter après un //dist//. N'appèle pas dist qui doit donc avoir été exécuté avant ! Copie dans un sous-répertoire défini par la propriété <ivy.distrib.dir> toutes les librairies nécessaire a eP-Core et eP-Core. Ceci afin de permettre a eP-Web, par exemple, de référencer ces librairies sans les intégrer. En effet; dans la distrib finale d'eP-Web (ou autre module de l'application J2EE) ne doit pas intégrer eP-Core mais référencera cette librairie intégrée a Geronimo. | ||
- | |||
- | ===== Architecture ===== | ||
- | Cette section décrit l’organisation des packages ainsi que les points d’interaction entre les objets des différents frameworks.eP-Core ne concernant pas tout ce qui se rapporte à la partie présentation, seuls les objets de persistance de données et ceux propre à la logique applicative sont définis. | ||
- | |||
- | ==== La théorie ==== | ||
- | |||
- | {{ epc_diagram_appli.png }} | ||
- | ** Figure 2 Diagramme de classe globale ** | ||
- | |||
- | * Les objets du package BO (BusinessObject) représentent les données du model (en l’occurrence celles de la base de données). Ces objets ne contiennent que des informations (des attributs) mais pas de ‘comportements’. Ils sont accessibles dans toutes les couches de l’application. | ||
- | * Le package DAO contient les classes qui ont la charge de la persistance des données (utilisation du framework Hibernate). Seules les interfaces doivent être accédées afin de permettre tout changement d’implémentation de manière transparente. En effet, le framework Spring permet de spécifier (aux classes services) la classe d’implémentation via le mécanisme d’inversion de contrôle (IoC) par injection par accesseur : utilisation d’un fichier de configuration et accès aux setter méthodes. Spring prend également en charge la gestion des sessions/transactions pour Hibernate : les classes DAO doivent étendre la classe HibernateDaoSupport qui prend en charge les accès JDBC. | ||
- | * Le package Service contient les interfaces qui doivent être utilisées par toutes les autres applications (ou couches) afin de manipuler (créer, modifier, supprimer) les objets de données. Les classes d’implémentation des services doivent définir des setter méthodes pour les classes DAO afin d’être configurées par Spring (voir paragraphe précédent). | ||
- | |||
- | En résumé, la couche model rend visible d’une part les objets représentant les données (package BO) et, d’autre part, les interfaces Services qui permettent de manipuler ces données. | ||
- | |||
- | On retrouve donc dans les fichiers de configuration xml : (spring-*.xml) | ||
- | |||
- | * La définition de la dataSource utilisée par Hibernate pour accéder à la DB. | ||
- | * La définition des différentes propriétés propres à Hibernate (mapping files…) | ||
- | * La définition des dao : description des beans et spécification de la propriété hibernateTemplate. | ||
- | * La définition des services : description du bean et spécification des propriétés qui seront positionnées via les accesseurs. | ||
- | |||
- | **REMARQUE** : ServiceLocator recherche dans l’ApplicationContext qui lui est spécifié les beans correspondants à l’implémentation de IXXXService (définit dans spring-*.xml). | ||
- | |||
- | ==== La pratique ==== | ||
- | === Utilisation d'un générateur d'Objets === | ||
- | La génération des POJOs et DAO se fait via MyEclipse Hibernate Reverse Engineering (HRE). Les hbms sont construits manuellement. | ||
- | Afin de permettre une séparation des POJOs et des DAO dans des packages différents la génération se fait en deux étapes : | ||
- | |||
- | == Génération des DAO == | ||
- | Depuis MyEclipse Database Explorer, sélectionner toutes les tables de la BD ePims sauf : | ||
- | - prog_contact | ||
- | - proj_contact | ||
- | - study_contact | ||
- | - samples_share | ||
- | |||
- | Dans les fenêtres d'HRE | ||
- | |||
- | * sélectionner le répertoire source "src/main" et le domain "cea.edyp.epims.domain.dao.impl". Sélectionner seulement la génération des DAO (en vérifiant que l'option "generate precise findBy methods" est décochée) et l'utilisation de template maison, en précisant le chemin "{workspace}/ep-Core\resources\templates", comme ci-dessous : | ||
- | |||
- | {{ epc_hre_dao.png }} | ||
- | ** Figure 3 MyEclipse Hibernate Reverse Engineering ** | ||
- | |||
- | * utiliser le fichier ./hibernate.reveng.xml comme "rev-eng settings file". Ce fichier permet de spécifier, entre autre, des nom de classes différentes que ceux proposés par défaut pour certaines tables : | ||
- | |||
- | o table ms_protocol => classe cea.edyp.epims.domain.dao.impl.MSProtocol | ||
- | o table msms_protocol => classe cea.edyp.epims.domain.dao.impl.MSMSProtocol | ||
- | o table gel_1d => classe cea.edyp.epims.domain.dao.impl.Gel1D | ||
- | o table gel_2d => classe cea.edyp.epims.domain.dao.impl.Gel2D | ||
- | o table gel_1d_migration => classe cea.edyp.epims.domain.dao.impl.Gel1DMigration | ||
- | o table gel_2d_migration => classe cea.edyp.epims.domain.dao.impl.Gel2DMigration | ||
- | o table sample_species => classe cea.edyp.epims.domain.dao.impl.Species | ||
- | o table sample_subcellular_localisation => classe cea.edyp.epims.domain.dao.impl.SubCellularLocalisation | ||
- | |||
- | Une fois les classes DAO générées il faut corriger les erreurs suivantes : | ||
- | |||
- | * ActorRoleDAO, méthode findByID: | ||
- | public ActorRole findById( cea.edyp.epims.domain.dao.impl.ActorRoleId id) => public ActorRole findById( cea.edyp.epims.domain.ActorRoleId id) | ||
- | * TreatmentsApplicationDAO, méthode findByID: idem ci dessus | ||
- | * StudyDAO, l'interface IStudyDAO qu'implémente cette classe définit en plus des méthodes "génériques" la méthode refreshLazy(). Par conséquent, cette classe doit êtredéfinie comme abstraite. La classe EPCoreStudyDAO, sous-classe de StudyDAO, implémente cette méthode. | ||
- | |||
- | **Attention** : A la première création des DAO, nous avons "extrait" les interfaces (via MyEclipse) dans le package cea.edyp.epims.domain.dao.*. Ceci afin de référencer les interfaces dans les services et éventuellement d'enrichir ces interfaces pour certaines classes. Dans ce cas des modifications sur les classes DAO générées sont nécessaires. | ||
- | Par exemple pour l'objet Study : | ||
- | |||
- | * Les objets du domaines cea.edyp.epims.domain.AbstractStudy et cea.edyp.epims.domain.Study sont généres (cf ci-dessous) | ||
- | * La classe cea.edyp.epims.domain.dao.impl.StudyDAO a été générée et l'interface cea.edyp.epims.domain.dao.IStudyDAO a été extraite de cette classe. | ||
- | * La méthode refreshLazy() a été ajoutée à l'interface IStudyDAO. Nous avons défini une classe EPCoreStudyDAO dérivée de StudyDAO qui implémente cette méthode. Par contre, la classe StudyDAO n'implément pas toutes les méthodes de IStudy, par conséquent une erreur est levée. Pour remédier à cela, la classe StudyDAO est déclarée abstraite. | ||
- | |||
- | {{ epc_dao_diagram.png }} | ||
- | ** Figure 4 Diagramme de classes exemple pour les DAO Hibernate ** | ||
- | |||
- | == Génération des POJO == | ||
- | Les Objets du domaines sont générés depuis les fichiers *.hbm.xml: | ||
- | |||
- | * Sélectionner tous les fichiers hbm.xml, | ||
- | * Cliquer droit avec la souris et choisir "MyEclipse -> Generate POJOS" | ||
- | * Dans la fenêtre "Hibernate Foward Engineering" | ||
- | |||
- | o spécifier src/main comme output folder, | ||
- | o cocher la case "Create abstract class" | ||
- | o ne pas cocher la case custom template | ||
- | |||
- | Seules les classes mères "AbstractXXX" sont systématiquement générées. Les sous classes ne sont générées que la première fois ce qui permet de les personnaliser sans tout perdre à chaque génération. | ||
- | |||
- | {{ epc_dao_diagram.png }} | ||
- | ** Figure 5 diagramme de classes exemple pour les objets du domaine ** | ||
- | |||
- | === Définition des Services === | ||
- | **__Accès__:** | ||
- | |||
- | Seules les interfaces IxxxService sont visibles depuis toute autre application (telle que la couche présentation) qui utilisera eP-Core. Ces interfaces devront fournir les méthodes nécessaires pour l’accès aux données en lecture et en écriture. | ||
- | |||
- | **__Règles de développement__** | ||
- | |||
- | Les méthodes pour l'écriture des données sont de la forme : | ||
- | |||
- | * public Sample saveSample(Sample sample)throws EPimsServiceException; Sauvegarde d'un élément (ici Sample) déjà existant. L'objet saivegardé est retourné. | ||
- | * public Sample createSample(Sample sample) throws EPimsServiceException; Création d'un nouvel élément. L'objet créé est retourné. | ||
- | * public void deleteSample(Sample sample) throws EPimsServiceException; Suppression d'un élément | ||
- | |||
- | Pour les accès en lecture, les services sont écrits selon le principe suivant : | ||
- | * on définit un objet enum contenant un ensemble de requêtes retournant des objets (du type de l'entité que représente le service) en appliquant des filtres specifics. | ||
- | * on définit une méthode générique (getSamples(enum.query, args)) permettant d'exécuter ces requêtes. Cette méthode reçoit une des requêtes prédéfinies en paramètre ainsi que le/les argument(s) dont peut avoir besoin cette requête, et retourne une liste des valeurs resultantes. | ||
- | |||
- | Il est certain que certaines actions ne peuvent être appliquées par une simple requête (aussi compliquée qu'elle puisse être !!), à ce moment là, les services peuvent aussi avoir des méthodes exécutant des tâches partiulières. | ||
- | |||
- | === Dans Spring: === | ||
- | Et au niveau des fichiers de configuration, on définit les beans. | ||
- | |||
- | * Dans le fichier// SpringAppContext.xml// : | ||
- | |||
- | <bean id="contactServiceTarget" class="cea.edyp.epims.service.impl.HibernateContactService"> | ||
- | <property name="actorDao"><ref bean="ActorDAO"></ref></property> | ||
- | <property name="contactDao"><ref bean="ContactDAO"></ref></property> | ||
- | <property name="actorRoleDao"><ref bean="ActorRoleDAO"></ref></property> | ||
- | <property name="companyDao"><ref bean="CompanyDAO"></ref></property> | ||
- | </bean> | ||
- | <!-- Transactional proxy Services --> | ||
- | <bean id="baseTransactionProwy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean" abstract="true"> | ||
- | <property name="transactionManager"><ref local="transactionManager"/></property> | ||
- | <property name="transactionAttributes"> | ||
- | <props> | ||
- | <prop key="get*">PROPAGATION_REQUIRED,readOnly</prop> | ||
- | <prop key="save*">PROPAGATION_REQUIRED</prop> | ||
- | <prop key="="create*">PROPAGATION_REQUIRED</prop> | ||
- | <prop key="="delete*">PROPAGATION_REQUIRED</prop> | ||
- | </props> | ||
- | </property> | ||
- | </bean> | ||
- | ... | ||
- | <bean id="contactService" parent="baseTransactionProxy"> | ||
- | <property name="target"><ref local="contactServiceTarget"/></property> | ||
- | </bean> | ||
+ | * [[ePCoreIntro]] | ||
+ | * [[ePCoreIntro#structure_du_projet|Structure du projet]] | ||
+ | * [[ePCoreArchitecture]] | ||
+ | * [[ePCoreSpring]] | ||
+ | * [[ePCoreHibernate]] | ||
+ | * [[ePCoreArchivage]] | ||
+ | * [[ePCoreRunRobot]] | ||
+ | * [[ePCoreFilesTransfer]] | ||
+ | * [[ePCoreProcessProtocol]] | ||
+ | * [[http://biodev.extra.cea.fr/ePims/dbModel/v6/index.html|DataModel (Version 6)]] |