Sites


Lutece : guide développeur

Description de l'architecture logicielle

Ce chapitre a pour objectif de décrire l'architecture logicielle de Lutece. Nous allons commencer par la description des différentes étapes de la requète HTTP d'un client à la réponse HTTP du serveur. Puis nous décrirons plus en détail l'organisation du code dans les différentes classes java, JSP, fichiers HTML et xsl. Enfin, nous verrons de manière exhaustive l'organisation de ces fichiers dans un projet lutece.

Architecture générale

Le choix général d'architecture repose sur la spécification Java EE qui apporte un cadre aux applications d'entreprise n-tiers.

Découpage général de l'architecture

Les choix de la conception détaillée se sont portés sur une architecture en quatre couches côté serveur :

  • La couche présentation assurant les fonctions de gestion de l'interface utilisateur.
  • La couche service assurant les fonctions d'interface entre la couche métier et la couche présentation, ainsi qu'un ensemble de services techniques : cache, transformations XML/XSL vers HTML ou HTML vers XHTML.
  • La couche métier assurant la gestion des objets modélisant l'activité métier.
  • La couche d'accès aux données qui assure la persistance des objets métiers.

Schéma de restitution du contenu

Le schéma suivant présente de manière simplifiée le processus de restitution d'un contenu Front Office. Le schema se lit de gauche à droite et représente les différentes étapes commençant à la requète HTTP du client et terminant à la réponse HTTP du serveur. Le schéma est suivi d'explications sur les différentes étapes, puis de descriptions détaillées des différentes couches.

lutece-architecture

 

Les différents composants sont representés par des symboles différents: ceux de la couche présentation par de simples rectangles, ceux de la couche service avec un engrenage, ceux de la couche métier et ceux de la couche d'accès au données par une feuille de papier.
Les couleurs indiquent en blanc les composants de lutece-core, en bleu les composants du plugin-document, un plugin standard de lutèce, et en vert des composants qui pourraient être apportés par un nouveau plugin.
Ce schema donne donc plusieurs exemples d'architecture dont on peut s'inspirer lors de l'écriture de nouveaux plugins.

 

Les étapes de restitution

  1. Comme vu précédemment, Portal.jsp est le point d'entrée de restitution.
    Comme toutes les JSPs dans Lutece, Portal.jsp utilise une directive <jsp:useBean> pour charger un bean java (ici PortalJspBean), ce qui permet d'écrire le code dans une classe java normale afin de faciliter la maintenance. PortalJspBean implémente des méthodes correspondant à différentes opérations de l'utilisateurs, et délègue la plupart des fonctionnalités à des classes java de services : PortalService, ContentService, AppPropertiesService, etc. Il n'est pour l'instant pas important de connaître tous ces services, et les plus importants seront présentés dans la suite de livre, mais l'organisation du code JSP/JSPBean/Service est un point central de Lutece.

  2. La suite du traitement consiste à utiliser les paramètres HTTP pour sélectionner un Content Service.
    Les Content Services sont des classes java comprenant principalement une méthode isInvoked indiquant selon les paramètres HTTP si c'est ce service qui est demandé, et une methode getPage renvoyant le contenu HTML en utilisant un cache. Les Content Services proviennent du coeur de Lutece ou de plugins.
    Pour reprendre les exemples du précédent chapitre, voici différents Content Services :
    1. PageContentService de lutece-core, paramètres HTTP "page_id=n". Ce Content Service gère les pages éditoriales du site. Ces pages sont configurées en back office en y organisant des portlets. Ces pages sont organisées en une arborescence du site Lutece reflétée dans les menus et le fil d'ariane.
    2. XPageAppService de lutece-core, paramètres HTTP "page=name". Ce Content Service gère des pages autonomes appelée  XPages fournissant des fonctionnalités spécifiques. Le contenu est entièrement fabriqué par la classe java appelée et n'est généralement pas aussi éditable que les pages du PageContentService avec leurs portlets.
    3. DocumentContentSerivce de plugin-document, paramètres HTTP "document_id=n&porlet_id=m". Ce Content service est fourni par le plugin document qui propose dans Lutece des contenus typés (par exemple, article, brève, etc.) organisés autour d'un workflow de publication (gestion de la collaboration, de la validation).

  3. 3a) Si une page du PageContentService est demandée, le bean s'adresse au PageService qui fournira la page si elle est dans son cache ou sinon il la construira. La construction d'une page fait appel à la classe PageHome pour obtenir une instance de la page demandée. Ensuite, le contenu de chaque rubrique de la page est récupéré en XML puis transformé à l'aide de la feuille de style XSL associée, et agrégé pour constituer la page. La nouvelle page construite est alors mise dans le cache. Ici, le point important d'architecture est que les class services s'appuient sur des classes d'objets métiers, par exemple PageHome et Page, qui chargent leur données depuis des objets DAO (Data Access Object), par exemple PageDAO.
    3b) et 3c) fonctionnent sur le même principe en s'appuyant sur des services techniques et des objets métiers différents.

Architecture logicielle par brique : description des couches logicielles

Couche de présentation

Cette couche est réalisée à l'aide de JSP, de Java Beans, éventuellement de servlets. Le code HTML est produit de deux manières :

  • Pour les éléments les plus dynamiques du portail (par exemple les documents de plugin-document), le HTML est produit par transformation du contenu XML à l'aide de feuilles de style. Le contenu XML pourra éventuellement contenir lui-même du code HTML pour tout ce qui concerne les contenus non structurés et notamment les pages locales.
  • Pour les élements qui ne requierent pas le support de plusieurs formats de restitution (par exemple le module d'administration ou les XPages), des fichiers contenant des modèles de représentation HTML appelés Templates seront utilisés.

Les JSP

Pour rappel, nous parlons ici de la catégorie à laquelle appartient Portal.jsp, le point d'entrée principal de restitution de contenus du Front Office.

De manière générale, le rôle attribué aux JSP est strictement limité à la gestion de la structure des pages et à la navigation. La partie HTML sera construite par des beans qui utiliseront des templates pour construire le code qui sera inséré dans les pages JSP.

Les JSP contiendront donc essentiellement :

  • la directive <jsp:useBean> qui charge un bean contenant la majorité du code.
  • la directive de redirection sur la page d'erreur : <%@ page errorPage="path/to/ErrorPage.jsp"%>
  • des directives d'inclusion d'objets statiques :<jsp:include> (ex : code HTML pour inclure une feuille de style)
  • des branchements conditionnels (<jsp:forward>)

Tout code Java et HTML est proscrit dans ces pages.

Les JSP doivent toutes contenir une JSP d'entête et une JSP de fin de page. Ceci permet d'intégrer dans toutes les pages des traitements initiaux et finaux sans avoir à modifier l'ensemble des pages (ex : test du timeout de la session, entête et pied de page HTML, lien vers une feuille de style, ajout de traitements statistiques, ...).

Le Front Office n'utilise principalement que Portal.jsp, alors que le Back Office utilise de nombreuses JSP. Cela permet d'avoir plus d'homogénéité dans le Front Office et plus de flexibilité dans le Back Office.

Les JspBeans

Pour rappel, nous parlons ici de la catégorie à laquelle appartient PortalJspBean, le bean associé à la JSP Portal.jsp vue dans les exemples.

Ces beans sont chargés de gérer la présentation des informations issues des objets métier. Ils doivent notamment produire du code HTML qui sera inséré dans les JSP. Ces composants sont regroupés dans le package fr.paris.lutece.portal.web pour le coeur de lutece, fr.paris.lutece.plugins.*.web pour les plugins. et ont un suffixe JspBean pour les différencier des beans métier.

Les JSP beans peuvent être utilisés par plusieurs pages JSP traitant des mêmes informations, notamment pour partager des constantes.

La portée des JSP beans (attribut scope dans la déclaration du bean dans la JSP) doit être soit session s'il contient des variables d'instance relative à la session de l'utilisateur (état conversationnel), soit request s'il n'a pas de variable d'instance. Dans certains cas, les scopes page ou applications sont aussi utilisés.

Les templates

Les templates sont des fichiers .html contenant un template de code HTML et éventuellement Javascript. Le moteur de template utilisé est FreeMarker http://freemarker.org. Par exemple, le template principal associé à Portal.jsp est le fichier page_frameset.html.

Après le templating Freemarker, certaines transformations additionnelles sont effectuées dans cet ordre :

1. Le traitement des libellés multilingue introduits sous la forme #i18n{key}. La gestion de l'internationalisation (i18n) sera décrite plus loin dans un chapitre dédié.

2. Le traitement des libellés sous la forme #dskey{key} dont les valeurs sont stockées en base de données (dans le datastore de Lutece).

3. Les traitements d'éventuels ContentPostProcessor comme ceux des plugins plugin-extend ou plugin-seo.

L'avantage de ces templates est qu'ils peuvent être partagés par plusieurs JSP et qu'ils peuvent être modifiés par des concepteurs graphiques sans risque d'impact sur les traitements. Ces templates seront stockés dans le répertoire /WEB-INF/templates.

Les feuilles de style XSL

Les feuilles de style XSL servent à transformer les contenus XML en HTML. Par ce mécanisme, on sépare le contenu de la forme. Par simple changement de style les mêmes contenus peuvent être présentés de manière très différente.

La couche métier

La couche métier est réalisée par un ensemble de classes correspondant à des objets métiers.

Ces classes ne contiennent aucun code technique HTML ou SQL. Ces composants sont regroupés dans les packages fr.paris.lutece.portal.business.* pour le coeur et fr.paris.lutece.plugins.*.business.* pour les plugins.

La persistance de ces objets est assurée par des objets DAO (Data Access Object) dont l'interface contient les principales méthodes d'accès aux données correspondant aux opérations SQL de base : load (SELECT), store (UPDATE), create (INSERT), delete (DELETE).

Nous avons décidé d'avoir une conception proche des Enterprise JavaBeans, et nous utilisons une classe "Home" pour chaque objet métier principal, c'est à dire disposant d'un DAO, inspirée des EJB Home Interface. Les prérogatives de ces classes sont, comme pour les EJB, d'assurer la gestion des instances de l'objet métier :

  • Création d'une instance (méthode create() )
  • Renvoi d'une instance à partir de sa clé primaire (méthode findByPrimaryKey())
  • Renvoi d'une collection d'instances pour un critère donné (méthodes findByCritère())

À ces méthodes qui figurent dans l'interface des classes Home des EJB entity, nous ajouterons les méthodes qui normalement correspondent à des actions gérées par le conteneur d'EJB. L'objet Home étant le seul objet ayant accès au DAO, c'est lui qui assurera les opérations de modification et de suppression des entités dans la base de données.

Les appels à ces méthodes seront effectués par le biais de méthodes update() et remove() au niveau de l'objet métier.

Voici le tableau récapitulatif des interfaces classiques des différents objets. Une ligne represente des méthodes liées, leur portée, et l'existance de cette méthode dans le modèle de programmation des EJB entity :

Objet Métier HomeDAO
Méthode Portée Méthode Portée  EJB? Méthode Portée EJB?
    create public X insert package X
    findByPrimaryKey public X load package X
    finbBy... public X selectBy package X
Update public update package   store package X
Remove public remove package   delete package X

Une recommandation importante de la conception d’EJB entity est d’avoir une granularité assez grosse, c'est à dire que tout objet métier ne doit pas nécessairement être implémenté sous la forme d’un EJB entity. Tous les objets métiers dépendant d’un objet métier principal, et particulièrement dans le cas où il est en lecture seule, doivent être implémentés sous la forme d’une classe simple. La lecture de cet objet sera alors réalisée au niveau du DAO de l’objet principal.

Les services

Les services servent à implémenter des fonctionnalités qui ne sont pas directement reliées à la création et modification d'un objet métier et de ses données. C'est souvent la partie la plus importante en termes de répartition de fonctionnalités d'une application.

C'est dans cette catégorie que se trouvent les Content Services, qui implémentent le framework dans lequel la majorité des contenus du Front Office sont restitués: PageContentService et XPageAppService.

Un certain nombre de services techniques fournis par le coeur sont accessibles à partir des composants de l’application : Par exemple:

ServiceDescription
AppTemplateService Renvoie un modèle HTML à partir de son nom. Ce service dispose d’un cache activable qui permet de ne pas relire sur disque un modèle qui a déjà été demandé.
AppConnectionService Fourniture de connexions à la base données à partir d’un pool. Ce service est paramétrable pour utiliser soit le pool du serveur d’application, soit un pool de connexions autonome.
AppPropertiesService Renvoie les valeurs des variables définies dans les fichiers properties des répertoires /WEB-INF/conf/ et /WEB-INF/conf/plugins/
MailService.java Permet l'envoi de mail en format text ou html, avec gestion d'évenements de calendrier.
I18nService.java Gère la traduction de chaines de caractères en fonction du choix de l'utilisateur
AppLogService.java Gère les logs avec différents niveaux de sévérité, différents loggers
XmlTransformerService.java Gère l'application de feuilles de styles XSL pour transformer des contenus XML.

Il ne s'agit pas ici de donner une liste exhaustive des différents services du coeur, car la nature des services fait que des fonctionnalités très variées sont y sont implémentées. Il est conseillé de parcourir le code du coeur et de plugins incontournables (par exemple plugin-document, plugin-directory) pour avoir des exemples de fonctionnalités à regrouper dans des classes de services.


Base de données Lutèce

Les requêtes SQL écrites dans les fichiers DAO doivent être compatible avec la norme SQL92.

Les requêtes SQL et les types de colonnes dans les scripts de création de la base de données doivent être compatibles avec les bases de données MySQL ou MariaDB. Le système de Lutece de création de la base de données basé sur Ant assure une transcription pour les SGDB PostgreSQL, HSQLDB et Oracle.


Organisation physique des fichiers de l'application

L’arborescence des répertoires dans le projet source de Lutece core est définie comme suit et intègre les spécifications JEE - Servlet 2.5.

Organisation des répertoires du noyau

LocalisationType de fichierDescription
src/java *.java Les sources de l’application
src/sql *.sql Les scripts de création de base et d’initialisation de l’application
<webapp>/css *.css Feuille de style CSS par défaut utilisée par l’application
<webapp>/images *.gif,*.jpg,*.png L'ensemble des pictogrammes utilisés par l’application
<webapp>/js *.js Fichiers javascripts utilisés dans l’ensemble de l’application
<webapp>/jsp/admin *.jsp Les Java Server Pages du module d’administration de l’application
<webapp>/jsp/admin/plugins *.jsp Les Java Server Pages de la fonctionnalité de gestion des plugins du module d’administration
<webapp>/jsp/site *.jsp Les Java Server Pages de la partie site de l’application
<webapp>/WEB-INF web.xml Fichier de configuration de l’application web (specs Servlet 2.5). Contient la déclaration des servlets de l’application
<webapp>/WEB-INF/conf *.properties
  • config.properties : le fichier de configuration de l'application.
  • db.properties : le fichier de configuration des pools de connexions aux bases de données. Il comprend notamment les déclarations suivantes :
    • Drivers JDBC
    • Sources de données
    • Nombre de connexions ouvertes à la création d’un pool
    • Nombre maximum de connexions par pool
    Ce fichier est utilisé pour un fonctionnement autonome (sans serveur d’application).
  • Autres fichiers properties
<webapp>/WEB-INF/index _*.f* et autres Les index du moteur de recherche Lucene pour le site de l’application
<webapp>/WEB-INF/indexall _*.f* et autres Les index du moteur de recherche Lucene pour un ensemble de sites définis dans le fichier config.properties
<webapp>/WEB-INF/lib *.jar Les fichiers archive contenant les classes importées dans l’application ainsi que ceux de lutece core. (specs Servlet 2.5)
<webapp>/WEB-INF/logs *.logs Les logs de l’application.
<webapp>/WEB-INF/taglibs *.tld Fichiers taglibs utilisés dans l’application
<webapp>/WEB-INF/templates/admin et sous répertoires *.html Les modèles HTML utilisés pour la construction dynamique des pages. Il s’agit de blocs de code HTML utilisés par les beans de présentation du module d’administration
<webapp>/WEB-INF/templates/site et sous-répertoires *.html Les modèles HTML utilisés pour la construction dynamique des pages. Il s’agit de blocs de code HTML utilisés par les beans de présentation du site
<webapp>/WEB-INF/tmp aucun fichier Répertoire utilisé dans les fonctionnalités d’ upload , doit être toujours vidé après le traitement
<webapp>/WEB-INF/xsl/admin *.xsl Les feuilles de style XSL de mise en forme du contenu XML sur le module d'administration
<webapp>/WEB-INF/xsl/normal *.xsl Les feuilles de style XSL de mise en forme du contenu XML sur le site


Organisation des répertoires des plugins

Un plugin peut nécessiter un ensemble assez important et divers de fichiers. Voici les répertoires désignés pour contenir ces fichiers.

LocalisationType de fichierDescription
/src/java/fr/lutece/plugins/<plugin_name>/business *.java Les fichiers sources java de la couche métier
/src/java/fr/lutece/plugins/<plugin_name>/service *.java Les fichiers sources java de la couche service
/src/java/fr/lutece/plugins/<plugin_name>/web *.java Les fichiers sources java de la couche présentation
/src/sql/plugins/<plugin_name> *.sql Les scripts SQL d'installation et d'initialisation des tables du plugin
<webapp>/jsp/admin/plugins/<plugin_name> *.jsp Les JSP des fonctions d'administration
<webapp>/images/local/skin/plugins/<plugin_name> *.gif,*.jpg,*.png Les images des fonctions d'administration
<webapp>/images/local/skin/plugins/<plugin_name> *.gif,*.jpg,*.png Les images de présentation de l'application
<webapp>/images/local/data/<plugin_name> *.gif,*.jpg,*.png Les images gérées comme des données du plugin
<webapp>/plugins/<plugin_name>/*.* Sous-répertoires, tous types de fichiers Emplacement réservé aux plugins ayant besoins de répertoires ou fichiers spécifiques
<webapp>/WEB-INF/conf/plugins/<plugin_name>.properties *.properties Le fichier de propriété .properties du plugin
<webapp>/WEB-INF/plugins *.xml, plugins.dat, plugin_2_2.dtd Le fichier de définition du plugin
/WEB-INF/templates/admin/plugins *.html Les templates des fonctions d'administration
/WEB-INF/templates/skin/plugins *.html Les templates de l'application accessibles du portail
/WEB-INF/lib/plugin_<plugin_name>_<version>.jar *.jar Le fichier jar contenant les classes du plugin

Il y a une erreur de communication avec le serveur Booktype. Nous ne savons pas actuellement où est le problème.

Vous devriez rafraîchir la page.