Portail / Sujets autour de la programmation / Programmation C/C++ sous Linux / Serveur d'application avec Qt 6 / Concepts généraux(Sommaire)

Chargement des ressources.

Mise à jour du 05/06/2024.

Hormis le système d'historisation et le gestionnaire de connexions PostgreSQL, les ressources utilisées par une application ne sont pas connues à l'avance. Elles doivent pouvoir être réellement quelconques. Cela crée une difficulté car les ressources seront instanciées par des classes existantes dans la librairie webapp. Or ces classes ne connaissant pas la nature des ressources à charger, il faut faire un effort de conception de l'architecture logicielle pour rendre ce chargement générique, c'est à dire indépendant de la nature même des ressources.

Comme la ressource est une classe quelconque et que nous avons déjà abordé ce problème, une ressource devra hériter de la classe IData. Cela permettra de stocker facilement cette ressource dans un dictionnaire de données de classe DataMap.

Ce choix fait, il nous faut un "créateur" (fabrique d eclasses) générique (classe abstraite) de ressources que devront hérités les créateurs concrets. C'est le rôle de la classe IResourceBuilder. Cette classe définit une méthode de création de la resssource qui retourne un pointeur intelligent sur la classe ancêtre IData.

Comme le contexte de l'application ne connait pas les ressources à charger, il faut lui transmettre une référence sur un objet chargé de l'ensemble des chargements des ressources de ce contexte. C'est le rôle de la classe ResourcesBuilders. Cetet classe recense l'ensemble des fabrique de classes de ressources.

Comme l'utilisateur n'interagit pas avec le chargement des applications, il faut transmettre au constructeur du contexte de chaque application un objet de classe ResourcesBuilders (ou d'une classe dérivée). C'est au serveur, lors de la phase d'initialisation de chaque application, de transmettre au contexte de chacune d'elle le fichier de configuration qui permettra à chaque fabrique de classe recensée de créer la ressource correspondante.

Lorsque le serveur "charge" une application, il commence par créer son contexte. Lors de la création de ce contexte, les ressources de l'application sont automatiqument fabriquées. Si la création d'une ressource échoue, l'application ne sera pas chargée.

L'intérêt de cette architecture est de ne créer les ressources qu'au moment nécessaire, de ne pas les conserver si la construction du contexte échoue et de ne pas conserver en mémoire les fabriques de classe de ressources une fois ces dernières ayant joué leur rôle.

Le schéma qui suit expose le principe et les classes mises en oeuvre :

Chargement des ressources

Comme les descripteurs des ressources sont dans le fichier de configuration de l'application, on devra y décrire le nom de la ressource et les paramètres qui permettent sa construction. Il appartient à l'objet dérivé de la classe IResourceBuilder de savoir interprété correctement ses paramètres. Ces derniers devront faire partie de la documentation de l'application.

Ressources "standards".

Compte tenu de la fréquence de leur emploi, la librairie webapp propose deux ressources standards :

  1. Un système de journalisation (classe chargeur : LogBuilder) ;
  2. Un gestionnaore de connexions PostgreSQL (classe chargeur : PgBuilder).

Nous allons montrer comment passer d'un objet de classe donnée et non forcément conçu pour être stocké dans un dictionnaire à un objet enregistrable dans ce genre de structure. Nous allons montrer cela avec le système d'historisation.

La librairie jmp propose la classe Logger comme base d'un système d'historisation. Cette classe n'hérite pas de la classe IData et n'est donc pas conçue pour être stockée dans un dictionnaire.

Nous commençons par créer une classe concrète LogContainer qui dérive de la classe IData et prend en paramètre de construction une objet de la classe Logger (agrégation au sens POO). Cette classe embarque donc notre système d'historisation et peut soit nous retourner un pointeur intelligent sur le système d'historisation (méthode générique), soit nous livrer directement l'objet du système d'historisation (méthode spécifique).

Ceci fait, nous poursuivons avec la réalisation de la classe LogBuilder qui est le chargeur de ressource concret dérivée de la classe IResourceBuilder. La méthode générique shared_ptr<IData> LogBuilder::createResources(QMap<QString,QString>& properties) construit un objet de classe LogContaineret retourne un pointeur intelligent qui le référence via sa classe ancêtre.

Prototype de démonstration.

Le prototype p46 crée un dictionnaire de chargeurs de ressources via la classe DefaultResourcesBuilder. Il ajoute un chargeur de système d'historisation (classe LogBuilder) et le stocke dans le dictionnaire de chargeurs de ressources sous la clef log. Il ajoute ensuite un créateur de gestionnaire de connexions PostgreSQL (classe PgBuilder) et le stocke dans le dictionnaire de chargeurs de ressources sous la clef pg. Cela ne demande que très peu d'effort puisque ces chargeurs "standards" sont déjà présents dans la librairie webapp.

Le créateur du système d'historisation est alors invoqué avec une liste de paramètres transmis sous forme d'une liste de propriétés. Le système de journalisation est ensuite récupéré et la bannière du journal inscrite dans un fichier.

Le créateur du gestionnaire de connexions PostgreSQL est ensuite invoqué. Là encore on lui transmet des paramètres sous forme d'une liste de propriétés. Toutefois, dans le cas d'un mot de passe chiffré, on ne peut généralement pas transmettre la clef sous cette forme pour des raisons évidentes de confidentialité. On utilise alors le 2ème paramètre de la méthode IResourceBuilder::createResources pour lui transmettre la clef de déchiffrement du mot de passe via un dictionnaire de classe DataMap.

Une fois le gestionnaire de connexion créé, on lui demande une connexion vers PostgreSQL afin d'exécuter une requête SQL.

Nous fournissons un lien vers le fichier sourcedu programme principal. Voici l'affichage du réésultat de l'exécution :

Presence de la clef [log] : Oui
Presence de la clef [pg] : Oui
"05/06/2024 19:13:29,839<INFOR>+-------------------------------------+"
"05/06/2024 19:13:29,839<INFOR>| version 1.2.3-beta1 : Prototype p46 |"
"05/06/2024 19:13:29,839<INFOR>+-------------------------------------+"
"05/06/2024 19:13:29,839<INFOR>(c) Jean-Marie Piatte 2023"
"05/06/2024 19:13:29,839<INFOR>log.filename = ~/aaa/p46"
"05/06/2024 19:13:29,852<INFOR>Nombre de lignes de la table APACHE.T_ACCESS = 83"

Rédaction par Jean-Marie Piatte (1983-2021)