Création de la ressource EMS Pets

De RAD Studio
Aller à : navigation, rechercher

Remonter à Tutoriel : Utilisation d'un client EMS pour accéder à une ressource EMS personnalisée

Pour commencer ce tutoriel, créez une nouvelle ressource EMS qui expose toutes les méthodes disponibles (voir Présentation des ressources EMS pour plus d'informations) et les implémente.

La ressource EMS Pets de ce tutoriel stocke des informations sur des animaux de compagnies (par exemple, leur nom et leur type) dans un fichier qui se trouve sur le serveur EMS. La ressource EMS Pets implémente les points de terminaison disponibles et l'application client EMS Pets peut récupérer la liste des animaux de compagnie ou modifier les informations stockées sur eux en appelant ces points de terminaison de ressource EMS Pets.

Création de la ressource EMS Pets

Vous devez créer une ressource EMS et définir les points de terminaison de ressource EMS qui sont exposés. Pour plus d'informations, voir Présentation des ressources EMS.

  1. Ouvrez l'expert Package EMS dans RAD Studio.
    • Pour Delphi : Fichier > Nouveau > Autre > Projets Delphi > EMS > Package EMS.
  2. Sélectionnez Créer un package avec la ressource.
    EMSPackageWizard1.png
  3. Ajoutez le nom de la ressource EMS et le type de fichier :
    • Nom de ressource : Pets
    • Type de fichier : Unité
    EMSPackageWizard2.png
  4. Sélectionnez les points de terminaison EMS que la ressource EMS expose. Pour ce tutoriel, sélectionnez tous les points de terminaison.
    EMSPackageWizard3.png
  5. Cliquez sur le bouton Terminer.
  6. Dans le Gestionnaire de projets, renommez l'unité en PetsResource.
  7. Enregistrez le projet.

Vous pouvez voir la ressource EMS créée dans l'onglet Code :

  • Pour Delphi :
  [ResourceName('Pets')]
{$METHODINFO ON}

  TPetsResource = class
  private
    FPetsManager: TPetsManager;
    function GetModuleDirectory: string;
    procedure CheckManager;
    function IdFromRequest(const ARequest: TEndpointRequest): Integer;
  public
    destructor Destroy; override;
  published
    [EndpointName('GetPets')]
    procedure Get(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    [EndpointName('GetPet')]
    [ResourceSuffix('{item}')]
    procedure GetItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    [EndpointName('AddPet')]
    procedure Post(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    [EndpointName('UpdatePet')]
    [ResourceSuffix('{item}')]
    procedure PutItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    [EndpointName('DeletePet')]
    [ResourceSuffix('{item}')]
    procedure DeleteItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
  end;
{$METHODINFO OFF}

procedure Register;

Création de l'unité Pet Type

Vous devez créer un objet défini par l'utilisateur qui sera transmis entre les méthodes de points de terminaison du client EMS et du serveur EMS en utilisant des objets JSON.

Remarque : Vous devez utiliser cette unité de données dans l'application client EMS pour sérialiser les données.

Créez une nouvelle unité Pet type pour votre application, en procédant comme suit :

  1. Dans le Gestionnaire de projets | cliquez avec le bouton droit dans le projet | Ajouter nouveau > Unité.
  2. Renommez l'unité en PetType.
  3. Créez un nouvel enregistrement TPet comme suit :
    • Pour Delphi :
     TPet = record
      private
        FId: integer;
        FKind: string;
        FName: string;
      public
        constructor Create(const AId: Integer; const AName, AKind: string);
        property Name: string read FName write FName;
        property Kind: string read FKind write FKind;
        property Id: integer read FId write FId;
      end;
    
  4. Ajoutez le code suivant à votre unité :
    • Pour Delphi :
    constructor TPet.Create(const AId: integer; const AName, AKind: string);
    begin
      FName := AName;
      FKind := AKind;
      FId := AId;
    end;
    
  5. Pour sérialiser l'objet Pet, vous devez créer la classe TPetJSON dans votre unité. Définissez-la de la façon suivante :
    • Pour Delphi :
     TPetJSON = class
      public
       class function JSONToPet(const AJSON: TJSONValue): TPet; static;
       class function JSONToPets(const AJSON: TJSONArray): TArray<TPet>; static;
       class procedure PetsToJSON(const APets: TArray<TPet>; const AJSON: TJSONArray); static;
       class procedure PetToJSON(const APet: TPet; const AJSON: TJSONObject); static;
      end;
    
  6. Ajoutez les clauses uses suivantes :
    • Pour Delphi :
    	uses System.JSON, System.Generics.Collections;
    
  7. Implémentez les méthodes de votre unité.
    • Pour Delphi :
    class function TPetJSON.JSONToPet(const AJSON: TJSONValue): TPet;
    begin
      Result := TPet.Create(AJSON.GetValue<integer>('id'),
        AJSON.GetValue<string>('kind'), AJSON.GetValue<string>('name'));
    end;
    
    class procedure TPetJSON.PetToJSON(const APet: TPet; const AJSON: TJSONObject);
    begin
      AJSON.AddPair('id', TJSONNumber.Create(APet.FId));
      AJSON.AddPair('kind', TJSONString.Create(APet.FKind));
      AJSON.AddPair('name', TJSONString.Create(APet.FName));
    end;
    
    class function TPetJSON.JSONToPets(const AJSON: TJSONArray)
      : TArray<TPet>;
    var
      LValue: TJSONValue;
      LList: TList<TPet>;
    begin
      LList := TList<TPet>.Create;
      try
        for LValue in AJSON do
          LList.Add(TPetJSON.JSONToPet(LValue));
        Result := LList.ToArray;
      finally
        LList.Free;
      end;
    end;
    
    class procedure TPetJSON.PetsToJSON(const APets: TArray<TPet>;
      const AJSON: TJSONArray);
    var
      LPet: TPet;
      LJSONObject: TJSONObject;
    begin
      for LPet in APets do
      begin
        LJSONObject := TJSONObject.Create;
        PetToJSON(LPet, LJSONObject);
        AJSON.Add(LJSONObject);
      end;
    end;
    

Ajout de l'unité Pets Manager

Ce tutoriel montre comment stocker les données Pets dans un fichier qui se trouve sur le serveur EMS (pets.ini). Pour accéder aux données de ce fichier et les gérer, une nouvelle unité appelée PetsManager est créée dans la ressource EMS Pets.

  1. Dans le Gestionnaire de projets | cliquez avec le bouton droit dans le projet | Ajouter nouveau > Unité
  2. Renommez l'unité en PetsManager.
  3. Créez la nouvelle classe TPetsManager comme suit :
    • Pour Delphi :
    type
      TPetsManager = class
        FUserID: string;
        FIniFile: TIniFile;
      private
        function EncodePet(const AName: string; const AKind: string): string;
        function DecodePetLine(const ALine: string; const AField: integer): string;
      public
        constructor Create(const ADirectory: string);
        destructor Destroy; override;
        function GetPets: TArray<TPet>;
        function GetPet(const AId: Integer; out APet: TPet): Boolean;
        procedure UpdatePet(const AId: Integer; const APet: TPet);
        procedure AddPet(const APet: TPet);
        function DeletePet(const AId: Integer): Boolean;
        function PetExists(const AId: Integer): Boolean;
      end;
    
  4. Ajoutez les clauses uses suivantes :
    • Pour Delphi :
    uses
      System.SysUtils, System.IniFiles, System.Generics.Collections, PetType,
      System.Classes, System.StrUtils, System.Types;
    
  5. Ajoutez le code suivant à votre unité :
    • Pour Delphi :
    constructor TPetsManager.Create(const ADirectory: string);
    var
      LPath: string;
    begin
      LPath := IncludeTrailingPathDelimiter(ExpandFileName(ADirectory)) + 'pets.ini';
      FIniFile := TIniFile.Create(LPath);
      FUserID := '0000';
    end;
    
    // Procedure to add a pet to the pets.ini file
    procedure TPetsManager.AddPet(const APet: TPet);
    begin
      FIniFile.WriteString(FUserID, APet.Id.ToString, EncodePet(APet.Name, APet.Kind));
    end;
    
    // Function to check if a pet exists in the pets.ini file
    function TPetsManager.PetExists(const AId: Integer): Boolean;
    begin
      Result := FIniFile.ValueExists(FUserID, AId.ToString);
    end;
    
    // Function to delete a pet from the pets.ini file
    function TPetsManager.DeletePet(const AId: Integer): Boolean;
    begin
      Result := PetExists(AId);
      if Result then
        FIniFile.DeleteKey(FUserID, AId.ToString);
    end;
    
    // Destructor
    destructor TPetsManager.Destroy;
    begin
      FIniFile.Free;
      inherited;
    end;
    
    // Function to get a specific pet from the pets.ini file
    function TPetsManager.GetPet(const AId: Integer; out APet: TPet): Boolean;
    var
      LName: string;
      LKind: string;
    begin
      Result := PetExists(AId);
      if Result then
      begin
        LName := DecodePetLine(FIniFile.ReadString(FUserID, AId.ToString, ''), 1);
        LKind := DecodePetLine(FIniFile.ReadString(FUserID, AId.ToString, ''), 0);
        APet := TPet.Create(AId, LName, LKind);
      end;
    end;
    
    // Function to get all pets from the pets.ini file
    function TPetsManager.GetPets: TArray<TPet>;
    var
      LList: TList<TPet>;
      LPet: TPet;
      LSection: TStrings;
      I: integer;
    begin
      LSection := nil;
      LList := nil;
      try
        LSection := TStringList.Create;
        LList := TList<TPet>.Create;
        FIniFile.ReadSectionValues(FUserID, LSection);
        for I := 0 to LSection.Count - 1 do
        begin
          LPet := TPet.Create(LSection.Names[I].ToInteger,
            DecodePetLine(LSection.ValueFromIndex[I], 1),
            DecodePetLine(LSection.ValueFromIndex[I], 0));
          LList.Add(LPet);
        end;
        Result := LList.ToArray;
      finally
        LList.Free;
        LSection.Free;
      end;
    end;
    
    // Function to update a pet from the pets.ini file
    procedure TPetsManager.UpdatePet(const AId: Integer; const APet: TPet);
    begin
      if PetExists(AId) then
        FIniFile.DeleteKey(FUserID, AId.ToString);
      FIniFile.WriteString(FUserID, AId.ToString, EncodePet(APet.Name, APet.Kind));
    end;
    
    // Function to encode the data (to be saved in the pets.ini file)
    function TPetsManager.EncodePet(const AName: string;
      const AKind: string): string;
    var
      LPet: string;
    begin
      LPet := AName + ',' + AKind;
      Result := LPet;
    end;
    // Function to decode a line from the pets.ini file
    function TPetsManager.DecodePetLine(const ALine: string;
      const AField: integer): string;
    var
      LPetField: TStringDynArray;
    begin
      LPetField := SplitString(ALine, ',');
      Result := LPetField[AField];
    end;
    

Ajout de l'implémentation aux points de terminaison de ressource EMS

Vous devez ajouter l'implémentation des méthodes de points de terminaison EMS.

  1. Ajoutez les clauses uses suivantes :
    • Pour Delphi :
       uses PetType, PetsManager;
    
  2. Créez la variable privée suivante dans votre ressource EMS :
    • Pour Delphi :
    private
        FPetsManager: TPetsManager;
    
  3. Ajoutez le code suivant à votre unité :
    • Pour Delphi :
    procedure TPetsResource.Get(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    var
      LPets: TArray<TPet>;
      LJSON: TJSONArray;
    begin
      LJSON := nil;
      try
        CheckManager;
        LPets := FPetsManager.GetPets;
        LJSON := TJSONArray.Create;
        TPetJSON.PetsToJSON(LPets, LJSON);
        AResponse.Body.SetValue(LJSON, True)
      except
        LJSON.Free;
        raise;
      end;
    end;
    
    
    procedure TPetsResource.GetItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    var
      LId: Integer;
      LPet: TPet;
      LJSON: TJSONObject;
    begin
      LId := IdFromRequest(ARequest);
      CheckManager;
      if FPetsManager.GetPet(LId, LPet) then
      begin
        LJSON := TJSONObject.Create;
        try
          TPetJSON.PetToJSON(LPet, LJSON);
          AResponse.Body.SetValue(LJSON, True);
        except
          LJSON.Free;
          raise;
        end;
      end
      else
        AResponse.RaiseNotFound('', Format('Id not found: %d', [LId]));
    end;
    
    procedure TPetsResource.Post(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    var
      LJSON: TJSONObject;
      LPet: TPet;
    begin
      if ARequest.Body.TryGetObject(LJSON) then
      begin
        CheckManager;
        LPet := TPetJSON.JSONToPet(LJSON);
        if FPetsManager.PetExists(LPet.Id) then
          AResponse.RaiseDuplicate('', Format('Can not add duplicate Id: %d', [LPet.Id]));
        FPetsManager.AddPet(LPet);
      end
      else
        AResponse.RaiseBadRequest('', 'JSON expected');
    end;
    
    procedure TPetsResource.PutItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    var
      LId: Integer;
      LPet: TPet;
      LJSON: TJSONObject;
    begin
      LId := IdFromRequest(ARequest);
      if ARequest.Body.TryGetObject(LJSON) then
      begin
        CheckManager;
        LPet := TPetJSON.JSONToPet(LJSON);
        if not FPetsManager.PetExists(LId) then
          AResponse.RaiseNotFound('', Format('Can not update unknown Id: %d', [LId]));
        FPetsManager.UpdatePet(LId, LPet);
      end
      else
        AResponse.RaiseBadRequest('', 'JSON expected');
    end;
    
    procedure TPetsResource.CheckManager;
    begin
      if FPetsManager = nil then
        FPetsManager := TPetsManager.Create(GetModuleDirectory);
    end;
    
    procedure TPetsResource.DeleteItem(const AContext: TEndpointContext; const ARequest: TEndpointRequest; const AResponse: TEndpointResponse);
    var
      LId: Integer;
    begin
      LId := IdFromRequest(ARequest);
      CheckManager;
      if not FPetsManager.DeletePet(LId) then
        AResponse.RaiseNotFound('', Format('Can not delete unknown Id: %d', [LId]));
    end;
    
    destructor TPetsResource.Destroy;
    begin
      FPetsManager.Free;
      inherited;
    end;
    
    function TPetsResource.GetModuleDirectory: string;
    begin
      Result := ExtractFilePath(StringReplace(GetModuleName(HInstance), '\\?\', '', [rfReplaceAll]));
    end;
    
    function TPetsResource.IdFromRequest(const ARequest: TEndpointRequest): Integer;
    var
      LItem: string;
    begin
      LItem := ARequest.Params.Values['item'];
      if not TryStrToInt(LItem, Result) then
        EEMSHTTPError.RaiseBadRequest('', Format('Id is not an integer: "%s"', [LItem]));
    end;
    
    procedure Register;
    begin
      RegisterResource(TypeInfo(TPetsResource));
    end;
    

Chargement de votre ressource EMS sur le serveur EMS

Le serveur EMS charge la ressource EMS Pets et expose les points de terminaison de ressource EMS Pets aux applications client EMS.

  1. Vérifiez que le serveur EMS est configuré dans votre système.
  2. Pour charger la ressource EMS Pets, appuyez sur F9 ou sélectionnez Exécuter > Exécuter.

La fenêtre Serveur de développement EMS est maintenant ouverte. Dans le volet Journal, vous voyez la ressource EMS Pets en cours de chargement.

{"Load":{"Filename":"C:\Users\Public\Documents\Embarcadero\Studio\15.0\Bpl\PetsResourcePackage.bpl","Thread":4072}}
{"RegUnit":{"Filename":"C:\Users\Public\Documents\Embarcadero\Studio\15.0\Bpl\PetsResourcePackage.bpl","Filename":"PetsResource","Thread":4072}}
{"RegResource":{"Resource":"Pets","Endpoints":["GetPets","GetPet","AddPet","UpdatePet","DeletePet"],"Thread":4072}}
EMSServerPetsResource.png

Voir aussi