Motivação

Há vários anos, a arquitetura padrão para o desenvolvimento de software foi o modelo cliente e servidor de duas camadas. Porém, com o grande advento dos dispositivos móveis, essa arquitetura já não é a mais adequada para várias aplicações. Isso ocorre porque pode ser custoso manter componentes de acesso a dados nos próprios aplicativos, visto que recursos de segurança e controles específicos do servidor precisam ser implementados manualmente. Por esses motivos é que se faz necessária uma arquitetura de software mais robusta para tais casos, e o modelo multicamadas utilizando a tecnologia de DataSnap traz a solução para esse problema.

Nesse modelo, é função do servidor de aplicação DataSnap manter todas as conexões com a base de dados, bem como todo o processamento das regras de negócio. Já à aplicação cliente caberá consumir os métodos que são expostos pelo servidor, obtendo assim os dados necessários a seu funcionamento. Nesse artigo nos concentraremos em como criar, no aplicativo cliente, métodos para listar dados provenientes do servidor DataSnap.

Passo 1: Criando o método no servidor

Quando criamos servidores DataSnap, automaticamente é gerada uma unit chamada ServerMethodsUnit, na qual devemos programar os métodos remotos que retornarão os dados para a aplicação cliente. Essa mesma unit também apresenta um visual muito semelhante ao um Data Module, e nela os componentes de acesso a dados devem ser adicionados. A Figura 1 mostra esses componentes: um FDConnection para realizar a conexão com a base de dados, um FDQuery para buscar os dados utilizando a SQL, o driver do banco de dados (FDPhysMSSQLDriverLink) e um FDStanStorageJSONLink, para permitir que os dados trafeguem pela rede no formato JSON.

Nesse exemplo estamos utilizando a engine FireDAC para acesso a dados e o SQL Server como sistema gerenciador de banco de dados. No entanto, caso necessário, outras tecnologias poderiam ser utilizadas de forma similar.

Componentes de acesso a dados
Figura 1. Componentes de acesso a dados

Tendo adicionado os componentes, podemos ver agora, na Listagem 1, a codificação para executar uma consulta no servidor e retornar os dados para a aplicação cliente. É importante frisar que deve-se adicionar na cláusula uses dessa unit o namespace Data.FireDACJSONReflect.

Listagem 1. Função para buscar os dados do servidor

        public
        function RetornaRegistros(): TFDJSONDataSets;
        end;
        function TServerMethods1.RetornaRegistros: TFDJSONDataSets;
        begin
        FDQuery1.Active := False;
        Result := TFDJSONDataSets.Create;
        FDQuery1.SQL.Text := "select * from pessoas";
        TFDJSONDataSetsWriter.ListAdd(Result, FDQuery1);
        end;
        
  • Linha 1: Início da seção public da unit, na qual os métodos remotos devem ser declarados;
  • Linha 2: Definição da assinatura do método. A classe TFDJSONDataSets permite que datasets no formato JSON trafeguem pela rede;
  • Linha 6: A query é fechada para a execução de um novo comando;
  • Linha 7: Criada a variável de retorno Result, do tipo TFDJSONDataSets, que armazenará o resultado da consulta em formato JSON;
  • Linha 8: É atribuído ao FDQuery a consulta que desejamos executar no servidor para retornar os respectivos registros para a aplicação cliente;
  • Linha 9: Por meio da classe TFDJSONDataSetsWriter, é adicionada na lista de retorno a variável Result juntamente com o FDQuery1, que será automaticamente executado e seus registros retornados para a parte cliente da aplicação.

Passo 2: Criando o método no cliente

Quando criamos clientes DataSnap, são gerados automaticamente pelo assistente do RAD Studio dois arquivos: ClientClasses e ClientModule. O primeiro é uma abstração de todos os métodos que foram definidos no servidor, enquanto o segundo efetivamente realiza as conexões entre a aplicação cliente e a aplicação servidora. A Figura 2 apresenta a interface gráfica, que é composta de um botão (TButton), um memo (TMemo), uma tabela em memória (FDMemTable1) e novamente o componente para permitir tráfego de arquivos JSON (FDStanStorageJSONLink1). O objetivo dessa interface é que quando o botão for clicado, será executada uma consulta utilizando o método do passo anterior, os resultados serão copiados para a tabela em memória e posteriormente listados no memo. É importante lembrar que é necessário informar na cláusula uses do formulário as units Data.FireDACJSONReflect e ClientModuleUnit1.

Interface gráfica do cliente
Figura 2. Interface gráfica do cliente.

Por fim, o código da Listagem 2 mostra como fazer o download dos dados do servidor e realizar a listagem.

Listagem 2. Download dos dados do servidor

        procedure Tform2.Button1Click(Sender: TObject);
        var
        dataset: TFDJSONDataSets;
        begin
        dataset := ClientModule1.ServerMethods1Client.RetornaRegistros();
        FDMemTable1.Active := false;
        FDMemTable1.AppendData(TFDJSONDataSetsReader.GetListValue(dataset, 0));
        FDMemTable1.Active := true
        while not FDMemTable1.Eof do
        begin
        Memo1.Lines.Add(FDMemTable1.FieldByName("nome").AsString);
        FDMemTable1.Next;
        end;
        end;
        
  • Linha 3: É definida a variável dataset, do tipo TFDJSONDataSets, que armazena os registros vindos do servidor;
  • Linha 5: É invocado o método RetornaRegistros declarado no servidor, acessado por meio da unit ClientModule1;
  • Linha 6: A tabela em memória é desativada para limpar a memória;
  • Linha 7: É invocado o método AppendData para preenchimento do FDMemTable1, o que é feito por meio da classe TFDJSONDataSetsReader. Os parâmetros do método GetListValue são a variável declarada na linha 3 e o índice do dataset. Como estamos retornando somente um dataset do servidor, esse índice é 0 (zero);
  • Linhas 8 a 14: Após o FDMemTable1 ser ativado, é executada uma estrutura de repetição para percorrer todos os registros e adicionar o campo nome no memo. Dessa forma, todos os nomes da base de dados serão listados.

Com isso, temos uma estrutura em DataSnap que faz a leitura dos dados no servidor e os copia para uma aplicação cliente. Conforme discutido anteriormente, essa codificação é comumente utilizada para trazer dados para aplicativos mobile utilizando um servidor de aplicação.