Tutoriel : Utilisation d'un serveur DataSnap avec une application

De RAD Studio
Aller à : navigation, rechercher

Remonter à Tutoriels Bases de données et LiveBindings


La technologie DataSnap fournit la capacité de créer des applications Client-Serveur qui communiquent par le biais d'Internet, du réseau local ou de l'hôte local.

L'exemple suivant illustre l'utilisation de DataSnap lors de la création d'une application Client-Serveur locale simple. Les applications client et serveur sont implémentées dans Delphi. Après la création du serveur et l'activation de la connexion entre le client et le serveur avec DataSnap, le client peut appeler des méthodes définies et implémentées sur le serveur.

Vous pouvez implémenter un serveur dans Delphi ou C++. Cet exemple présente les deux. Il n'est pas nécessaire que le client soit implémenté dans le même langage. DataSnap vous permet d'avoir un serveur Delphi et un client C++, ou vice-versa.

Composants serveur DataSnap clés

Les principaux composants sont :

Le composant TDSServer est le coeur logique de l'application serveur DataSnap. Il contient les méthodes Start et Stop pour le démarrage et l'arrêt du serveur. Il contient aussi la propriété AutoStart. Par défaut, la valeur de la propriété AutoStart est définie sur True. Ainsi, le serveur démarre automatiquement au démarrage de l'application. Vous avez besoin d'un seul composant TDSServer par application serveur.

Le composant TDSServerClass représente une classe serveur.

Le serveur DataSnap crée et détruit automatiquement les instances des classes serveur. L'instanciation d'une classe serveur est contrôlée par la propriété LifeCycle du composant TDSServerClass. La propriété LifeCycle a trois valeurs possibles : Serveur, Session et Invocation.

  • La propriété LifeCycle définie sur Serveur signifie que le serveur DataSnap crée une instance d'une classe serveur qui est utilisée par tous les clients connectés à l'application serveur. Cela représente un pattern "singleton". Soyez prudent lors de l'utilisation du cycle de vie Serveur, car votre implémentation de classe serveur nécessite d'être thread-safe : vous devez concevoir la classe serveur afin qu'elle soit accessible simultanément par plusieurs threads.
  • La valeur par défaut de LifeCycle est Session. Cela signifie que le serveur DataSnap crée une instance d'une classe serveur pour chaque client connecté.
  • La troisième valeur possible de la propriété LifeCycle est Invocation. Dans ce cas, une instance de classe serveur est créée et détruite pour chaque appel de méthode provenant d'un client, et l'état d'une classe serveur n'est pas préservé entre les appels de méthodes.

Un composant est aussi nécessaire pour fournir la communication entre le client et le serveur.

Le composant TDSTCPServerTransport implémente un serveur TCP multithread écoutant les connexions client entrantes sur plusieurs threads. Ce composant n'a pas d'événements. La propriété Port indique le port TCP à utiliser. Par défaut, elle est définie sur 211. Vous pouvez aussi utiliser HTTP pour la communication entre le client et le serveur.

Création de l'application serveur

  1. Créez un nouveau projet.
    • Pour Delphi, choisissez Fichier > Nouveau > Application Fiches VCL - Delphi dans le menu principal.
    • Pour C++, choisissez Fichier > Nouveau > Application Fiches VCL - C++Builder dans le menu principal.
    Changez la propriété Caption de la fiche en ServerForm.
  2. Placez les composants suivants de la catégorie Serveur Datasnap de la palette d'outils sur la fiche :
Cliquez sur l'élément de menu principal Fichier > Tout enregistrer. Enregistrez le fichier sous MyServer et le projet sous MyServerProj.
A ce stade, votre application serveur doit ressembler à ceci :
DS App1.jpg


Suivez les étapes ci-après pour lier les trois composants ensemble :
  • Sélectionnez le composant TDSServerClass sur la fiche. Définissez sa propriété Server sur le nom de votre composant TDSServer, DSServer1 dans cet exemple.
  • Sélectionnez le composant TDSTCPServerTransport sur la fiche. Définissez sa propriété Server sur le nom de votre composant TDSServer, DSServer1 dans cet exemple.
  1. Ajoutez une nouvelle unité à votre projet.
    • Pour Delphi, sélectionnez Fichier > Nouveau > Unité - Delphi dans le menu principal.
    • Pour C++, sélectionnez Fichier > Nouveau > Unité - C++Builder dans le menu principal.
    Enregistrez l'unité dans le fichier MyClass.pas pour Delphi ou MyClass.cpp pour C++. Cette unité contient l'implémentation des classes du serveur que vous voulez utiliser dans l'application client. Dans cet exemple, le code suivant représente l'implémentation d'une classe appelée MyClass qui contient une méthode : la somme de deux nombres à virgule flottante :
  2. Delphi

    unit MyClass;
    
    interface
    uses Classes;
    type
      {$METHODINFO ON}
      TMyClass = class(TComponent)
        function Sum(const A, B: Double): Double;
      end;
      {$METHODINFO OFF}
    
    implementation
    { TMyClass }
    function TMyClass.Sum(const A, B: Double): Double;
    begin
      Result := A + B;
    end;
    
    end.
    

    Remarque : La directive {$METHODINFO ON} provoque la génération des informations d'exécution requises par le serveur Datasnap. Ainsi, cela est nécessaire, ce n'est pas simplement un commentaire ! Pour de plus amples informations, voir Directive METHODINFO (Delphi).

    C++

    Placez le code suivant dans MyClass.h :

    # include <DSServer.hpp>
    
    class DECLSPEC_DRTTI TMyClass : public TComponent
    {
    private:
    public:
      double Sum(const double A, const double B);
    };
    # endif
    

    Placez le code suivant dans MyClass.cpp :

    double TMyClass::Sum(const double A, const double B)
    {
      return A + B;
    }
    

    Remarque : DataSnap supporte RTTI lors de la conception des applications C++. La déclaration DECLSPEC_DRTTI, similaire à la directive {$METHODINFO ON} provoque la génération des informations d'exécution requises par le serveur DataSnap, et cela est nécessaire.

    • Pour Delphi, ajoutez le nom de cette unité, MyClass, à la clause uses de l'unité de l'application serveur MyServer.pas.
    • Pour C++, ajoutez cette ligne à MyServer.h :
    # include "MyClass.h"
    
  3. Pour spécifier la classe que vous voulez appeler depuis l'application client, définissez l'événement OnGetClass pour le composant TDSServerClass : Dans l'onglet Conception de MyServer :
    1. Sélectionnez le composant TDSServerClass sur la fiche.
    2. Sélectionnez l'onglet Evénements de l'inspecteur d’objets.
    3. Double-cliquez sur la valeur relative à l'événement OnGetClass.
    4. Dans cette fonction juste générée, ajoutez une ligne de code, qui définit PersistentClass :

    Delphi

    procedure TForm1.DSServerClass1GetClass(DSServerClass: TDSServerClass;
      var PersistentClass: TPersistentClass);
    begin
      PersistentClass := TMyClass;
    end;
    

    C++

    void __fastcall TForm1::DSServerClass1GetClass(TDSServerClass *DSServerClass, TPersistentClass &PersistentClass)
    
    {
      PersistentClass = __classid(TMyClass);
    }
    
    Si l'implémentation de cet événement échoue, l'application déclenche une exception TDBXError avec ce message immédiatement après le lancement :
    L'événement OnGetClass n'est pas défini ou il n'a pas fourni une référence de classe
    L'événement OnGetClass a l'argument PersistentClass qui est passé par référence. Dans le code du gestionnaire d'événements, le développeur doit assigner à PersistentClass une référence de classe à une classe serveur, comme dans l'exemple ci-dessus.
    C'est probablement le concept le plus important à assimiler à propos de l'architecture DataSnap. Une référence de classe est assignée à PersistentClass, et pas une référence d'objet.

Ceci termine l'implémentation de l'application serveur.

Création de l'application client

  1. Pour créer l'application client dans le même groupe de projets que l'application serveur, cliquez avec le bouton droit sur le nom de votre groupe de projets dans le Gestionnaire de projets et sélectionnez Ajouter un nouveau projet dans le menu contextuel ou choisissez Projet > Ajouter un nouveau projet dans le menu principal. La boîte de dialogue Nouveaux éléments apparaît.
    • Pour Delphi, sélectionnez la catégorie Projets Delphi, puis sélectionnez Application Fiches VCL et cliquez sur OK.
    • Pour C++, sélectionnez la catégorie Projets C++Builder, puis sélectionnez Application Fiches VCL et cliquez sur OK.
    Définissez les propriétés Caption et Name de la fiche sur ClientForm. Cliquez sur l'élément de menu principal Fichier > Tout enregistrer. Enregistrez le fichier sous MyClient et le projet sous MyClientProj. Enregistrez le groupe de projets dans DSServerExample.
  2. Remplissez la fiche client avec les contrôles utilisés pour l'introduction des données et l'écriture du résultat (libellés, zones d'édition et un bouton pour calculer la somme), comme illustré dans la figure suivante. Définissez la propriété Name du contrôle TEdit auprès du libellé A sur EditA, et la propriété Name du contrôle TEdit auprès du libellé B sur EditB. Définissez la propriété Name du contrôle TEdit Result sur EditResult. Définissez la propriété Text de tous les contrôles TEdit sur "vide". Définissez la propriété Caption du contrôle TButton sur Calculate.
  3. Ajoutez un composant TSQLConnection depuis la catégorie dbExpress de la palette d'outils. Définissez les propriétés suivantes pour le composant TSQLConnection :
    • Driver : Datasnap (depuis la perspective du client, ce fournisseur ressemble à une connexion à une base de données, mais fournit en fait la connectivité aux serveurs DataSnap).
    • LoginPrompt : False (facultatif, pour empêcher l'affichage de la boîte de dialogue relative au nom d'utilisateur et au mot de passe à chaque connexion du client au serveur).
La fiche client a maintenant l'aspect suivant :
DSAppClientForm.png


  1. L'étape la plus importante lors de la création de l'application Client-Serveur avec DataSnap est la création de l'interface qui contient le prototype de toutes les fonctions implémentées sur le serveur. Procédez comme suit :
    • Sélectionnez le projet serveur en double-cliquant sur le nom du projet serveur, MyServerProj, dans le Gestionnaire de projets.
    • Choisissez Exécuter > Exécuter sans débogage dans le menu principal pour exécuter le serveur. Vous pouvez réduire la boîte de dialogue ServerForm qui s'affiche.
    • Pendant que le serveur est en cours d'exécution, sélectionnez le projet client en double-cliquant sur son nom, MyClientProj, dans le Gestionnaire de projets.
    • Dans l'onglet Conception, définissez la propriété Connected du composant TSQLConnection sur True.
    • Cliquez avec le bouton droit sur le composant TSQLConnection dans la fiche Client et cliquez sur Générer les classes client DataSnap dans le menu contextuel. Une nouvelle unité est ajoutée à votre projet client, contenant des informations sur les classes implémentées sur le serveur et toutes les méthodes contenues par ces classes.
      • Pour Delphi, enregistrez la nouvelle unité sous MyDSClient.pas et ajoutez le nom MyDSClient de cette unité à la liste des unités de MyClient.pas.
      • Pour C++, enregistrez la nouvelle unité sous MyDSClient.cpp. Ajoutez la ligne #include "MyDSClient.h" au début de MyClient.cpp.
  2. Appelez les méthodes désirées de l'application client. Dans cet exemple, implémentez l'événement OnClick pour le composant TButton afin d'appeler la méthode Sum de l'unité client DataSnap que vous venez de générer automatiquement. La classe générée est ici TMyClassClient et le gestionnaire d'événements du bouton est TClientForm.CalculateClick (Delphi) ou TClientForm::Button1Click (C++).
  3. Delphi

    procedure TClientForm.CalculateClick(Sender: TObject);
    var
      Temp: TMyClassClient;
      A, B: Double;
    begin
      Temp := TMyClassClient.Create(SQLConnection1.DBXConnection);
    try
      A := StrToFloat(EditA.Text);
      B := StrToFloat(EditB.Text);
      EditResult.Text := FloatToStr(Temp.Sum(A, B));
    finally
      Temp.Free;
    end;
    

    C++

    void __fastcall TClientForm::Button1Click(TObject *Sender)
    {
      TMyClassClient *Temp;
      double A, B;
    
      Temp = new TMyClassClient(SQLConnection1->DBXConnection);
      try
      {
        A = StrToFloat(EditA->Text);
        B = StrToFloat(EditB->Text);
        EditResult->Text = FloatToStr(Temp->Sum(A, B));
      }
      __finally
      {
        delete Temp;
      }
    }
    
  4. Finalement, construisez et exécutez l'application client. La fiche client est affichée. Entrez des nombres décimaux dans les champs A et B, et cliquez sur le bouton Calculate. La somme devrait apparaître dans le champ Result.
  5. Si vous obtenez un message d'erreur contenant le texte

    Connection ne peut être à nil. Vérifiez que la connexion a été ouverte.

    Vous n'avez probablement pas défini la propriété Connected du composant TSQLConnection sur True.

DSAppClientRunning.png


Remarque : Avant de terminer l'application serveur, n'oubliez pas de fermer toutes les connexions SQL. Dans cet exemple, définissez la propriété Connected du composant TSQLConnection du client sur False. DataSnap ne fournit pas d'avertissement à propos des connexions en attente. Ainsi, même si le serveur semble se fermer, il ne se ferme pas tant que des connexions au serveur existent. La fermeture de toutes les applications client ne résout pas ce problème, car l'EDI de Delphi peut ouvrir automatiquement une connexion au serveur et parcourir les méthodes et les classes exposées.

Voir aussi