Nosso objetivo neste artigo é oferecer um passo-a-passo para desenvolver uma aplicação simples multi-camadas sendo que:

  • o servidor de aplicação será implementado com o Delphi 2010 fazendo uso da tecnologia DataSnap 2010/DBExpress e irá atuar como servidor de dados com capacidades para aceitar chamadas HTTP/REST a seus métodos e criar respostas de dados usando o formato de dados JSON, como uma alternativa ao XML;
  • como cliente iremos criar uma interface em flex que será capaz de consumir as respostas produzidas pelo nosso servidor de aplicação.

Os requisitos são:

  • Delphi 2010;
  • Firebird 2.x;
  • Adobe Flash Builder 4;
  • IBExpert.

Não está no escopo explicar as novidades e conceitos de DataSnap 2010, bem como explicar o formato JSON. Não trataremos da IDE do Adobe Flash Builder 4 nem da linguagem Action Script e sim, apenas demonstrar de forma prática para fins didáticos a quem tiver interesse no assunto, como dar os primeiros passos na integração destas ferramentas.

Faremos pequenos métodos em nosso servidor que irão construir objetos e arrays do tipo JSON.

Para tanto sugerimos que crie na raiz C: uma pasta chamada DelphiFlex e dentro duas pastas: uma delphi e uma flex. Estas serão respectivamente as pastas onde iremos salvar o servidor de aplicação feito em Delphi e o cliente feito em flex.

Criaremos também um banco de dados chamado CONTATOS.FDB. Para isto use o IbExpert Free ou seu front-end preferido.

Para facilitar execute o script a seguir mudando a senha para a senha do SYSDBA do seu Firebird:

SET SQL DIALECT 3;
SET NAMES ISO8859_1;
SET CLIENTLIB 'fbclient.dll';
CREATE DATABASE 'C:\DelphiFlex\Delphi\CONTATOS.fdb'
USER 'SYSDBA' PASSWORD 'A'
PAGE_SIZE 4096
DEFAULT CHARACTER SET ISO8859_1;

CREATE TABLE CONTATOS (
    CODIGO  INTEGER NOT NULL,
    NOME    VARCHAR(50)
);

ALTER TABLE CONTATOS ADD CONSTRAINT PK_CONTATOS PRIMARY KEY (CODIGO);

INSERT INTO CONTATOS (CODIGO, NOME) VALUES (1, 'FELIPE DOS SANTOS');
INSERT INTO CONTATOS (CODIGO, NOME) VALUES (2, 'MARCELO FARIA');
INSERT INTO CONTATOS (CODIGO, NOME) VALUES (3, 'PAULO MACHADO');
INSERT INTO CONTATOS (CODIGO, NOME) VALUES (4, 'RODRIGO VIEIRA');
COMMIT WORK;

Crie uma nova aplicação Delphi. Para isso clique em File > New > Other e na janela New Items, na pasta Delphi Projects selecione a sub-pasta DataSnap Server e clique no item DataSnap Server:

DataSnap Server

Clique em OK e em seguida, na janela New DataSnap Server selecione VCL Forms Applications: marque a caixa HTTP e selecione em Ancestor a opção TPersistent e desmarque a opção Include sample methods:

TPersistent

Clique em OK e assim anova aplicação será criada, onde será adicionada três units: Unit1, ServerMethodsUnit1 e ServerContainerUnit1.

Na unit Unit1:

  • Renomeie a propriedade Name para FrmPrincipal;
  • Modifique a propriedade caption para Servidor;
  • Adicione um componente TMemo localizado na aba Standard e e configure a propriedade Align para alClient e na propriedade Lines apague o conteúdo.

Na unit ServerMethodsUnit1:

  • Renomeia o nome da classe para TSMContato.

Na unit ServerContainerUnit1:

  • Renomeie a propriedade Name para SCContato;
  • Selecione o componente DSServerClass1 e renomeia a propriedade Name para DSServerClassContato.

Pressione (Ctrl + Shift + S) para salvar: salve a unit ServerMethodsUnit1 como uSMContato, salve a unit ServerContainerUnit1 como uSCContato e a unit Unit1 como uFrmPrincipal e o projeto como Servidor.

Para configurar a conexão clique em View > DataExplorer e clique com o botão direito do mouse no item FIREBIRD e no menu suspenso que abrirá clique com o botão esquerdo do mouse em Add New Connection;

Na janela que abrirá, em Connection Name digite, CONTATOS. Clique em OK. Sobre a conexão recém criada de nome CONTATOS clique com o botão direito do mouse e no menu suspenso que abrirá clique com o botão esquerdo do mouse em Modify Connection:

Na Janela Modify Connection, no campo Database Name informe o caminho do banco de dados seguido do nome do banco de dados, nome do usuário e senha. Use a senha do SYSDBA do seu Firebird:

Firebird

Clique em OK.

Na unit FrmPrincipal:

  • Adicione um componente TSQLConnection e um componente TSQLDataSet ambos localizados na aba DBExpres.

Selecione o componente SQLConnection1:

  • No object inspector altere a propriedade ConnectionName para CONTATOS;
  • A proprieade LoginPrompt para False;
  • E configure como True a propriedade Connected.

Selecione o SQLDataSet1:

  • Altere a propriedade Name para DstContatos;
  • Configure a propriedade SQLConnection para SQLConnection1;
  • Digite na propriedade CommandText o seguinte:
SELECT * FROM CONTATOS WHERE NOME LIKE :PNOME

Nesse ponto sua configuração ao banco de dados já estará pronta.

Selecione a Unit uSMContato:

  • Adicione no uses a unit DBXJSON;
  • Em seguida clique em File > Use Unit e selecione a Unit uFrmPrincipal e clique em OK;
  • Crie uma função chamada GetContatos na sessão public;

Abaixo postamos a assinatura e o código completo da função GetContatos:

function GetContatos(pnome: string): TJSONArray;

function TSMContato.GetContatos(pnome: string): TJSONArray;
var
   I: Integer;
   qtdeCampos: Integer;
   ja: TJSONArray;
   jo: TJSONObject;
begin
   FrmPrincipal.Memo1.Lines.Add('passei no metodo GetContatos INICIO');

   FrmPrincipal.DSTContatos.Params.ParamByName('PNOME').AsString := '%' + pnome + '%';
   FrmPrincipal.DSTContatos.Open;
   FrmPrincipal.DSTContatos.First;

   qtdeCampos := FrmPrincipal.DSTContatos.FieldCount - 1;

   ja := TJSONArray.Create;

   while not FrmPrincipal.DSTContatos.Eof do
   begin
      jo := TJSONObject.Create;
      for I := 0 to qtdeCampos do
         jo.AddPair(FrmPrincipal.DSTContatos.Fields[I].FieldName, 
          TJSONString.Create(FrmPrincipal.DSTContatos.Fields[I].AsString));
      ja.AddElement(jo);
      FrmPrincipal.DSTContatos.Next;
   end;
   FrmPrincipal.DSTContatos.Close;
   Result := ja;
   FrmPrincipal.Memo1.Clear;
   FrmPrincipal.Memo1.Lines.Add(Result.ToString);
   FrmPrincipal.Memo1.Lines.Add('passei no metodo GetContatos FIM');
end;

Selecione a unit uSCContato:

  • Na cláusula uses renomeie ServerMethodsUnit1 para uSMContato;
  • Selecione o componente DSServerClassContato e, no object inspector, selecione a aba eventos, clique duplo sobre o evento onGetClass e substitua o código:
PersistentClass := ServerMethodsUnit1.TServerMethods1;

pelo código:

PersistentClass := uSMContato.TSMContato;

Selecione o componente DSHTTPService1 e altere a propriedade HttpPort para 8081. Caso esta porta já esteja sendo usado por outra aplicação, digite outro número de porta.

Pressione (Ctrl + Shift + S) para salvar. Compile a aplicação com F9. Se alguma mensagem para desbloquear a aplicação for apresentada, apenas confirme para desbloquear.

Teste no navegador executando o seguinte comando:

http://localhot:8081/datasnap/rest/TSMContato/GetContatos

ou a mesma sintaxe apenas mudando para a sua porta:

http://localhot:suaPorta/datasnap/rest/TSMContato/GetContatos

Deverá ser apresentado no navegador o seguinte resultado:

resultado

Para podermos criar nosso projeto em Flex, é necessario que você tenha o Adobe Flash Builder 4 instalado em sua máquina.

Caso não tenha, você poderá baixar uma versão trial (60 dias de uso) pelo link a seguir: https://www.adobe.com/cfusion/tdrc/index.cfm?product=flash_builder

Após clicar em "Clique para Baixar" você será redirecionado para a página da Adobe. Para efetuar o download, é necessário cadastrar-se.

Após ter concluído o cadastro, na página que abrir, clique em "Download Flash Builder 4 Installer for Windows" no bloco "Flash Builder 4 Standalone Installer.

Com o Flash Builder 4 instalado crie um novo projeto flex usando a opção File > New > Flex Project, conforme a imagem abaixo:

Flex Project

Como sugestão, preencha o campo "Project Name" com "Projeto Flex".No campo "Folder" selecione o caminho "C:\DelphiFlex\Flex" e clique no botão "Finish", conforme sugerido na imagem abaixo:

Projeto Flex

Selecione a aba "Designer" e clique em Window > Components. Irá aparecer uma guia de componentes e dentro de "Controls" clique e araste 1 "TextInput", 1 "Button" e 1 "DataGrid" para o projeto.

  • Selecione o TextInput e na guia "Common" altere seu id para "txt_consulta".
  • Selecione o Button e na guia "Common" altere seu Label para "Consultar".
  • Seleciona o DataGrid e na guia "Common" altere seu id para "DataGrid" e clique no botão "Configure Columns".
  • Selecione o item "Column 1" e altere os campos "Bind to field" e "Header text" do para "CODIGO" e "Width" para "100".
  • Selecione o item "Column 2" e altere os campos "Bind to field" e "Header text" do para "NOME" e "Width" para "200".
  • Apague o item "Column 3".

O próximo passo é baixar a biblioteca CoreLibAS3 acessando o link "http://code.google.com/p/as3corelib/downloads/list".

Após ter concluído o download descompacte o arquivo baixado. Dentro da pasta descompactada, abra a pasta "src" e copie a pasta "com" para a pasta "C:\DelphiFlex\Flex\src\".

Agora selecione a aba "Source", e adapte o código conforme o exemplo abaixo, onde comentamos a maior parte dos códigos:

<?xml version="1.0" encoding="utf-8"?>
<s:Application xmlns:fx="http://ns.adobe.com/mxml/2009" 
               xmlns:s="library://ns.adobe.com/flex/spark" 
               xmlns:mx="library://ns.adobe.com/flex/mx" height="212" width="327">
    <fx:Script>
        <![CDATA[
            //AQUI VAI O CÓDIGO ACTION SCRIPT
            import com.adobe.serialization.json.JSON; 
           //biblioteca responsável por converter do formato JSON 
           //para objetos nativos do Action Script e vice-versa 
            import mx.collections.ArrayCollection;
            import mx.rpc.events.ResultEvent;
            import mx.rpc.http.HTTPService; 
            
            //a função Consultar será responsável por invocar 
           //a URL e receber os dados da requisição
            private function Consultar():void{
                var ht:HTTPService = new HTTPService(); 
                //cria o serviço HTTPService sendo que ht é a variável 
               //de instância que faz referência para o objeto contendo o serviço 
                ht.showBusyCursor = true; 
                //para que apareça a ampulheta enquanto aguarda o resultado da requisição
                //define no serviço a URL seguido do parâmetro de consulta
                ht.url = "http://localhost:8081/datasnap/rest/TSMContato/GetContatos/" 
                 + txt_consulta.text;
                //define no serviço uma função que será responável por 
                //receber o resultado da requisição feita ao servidor. 
                //Neste caso criamos ConsultarResultado
                //que recebe de ResultEvent.RESULT o resultado da requisição
                ht.addEventListener(ResultEvent.RESULT, ConsultarResultado);
                ht.send(); //envia a requisição
            }
            
            //a função ConsultarResultado é responsável por processar 
            //as informações recebidas da requisição feita à URL do servidor
            private function ConsultarResultado(re:ResultEvent):void{
                //neste ponto criamos um objeto em Action Script usando var jo:Object
                //Em seguida, de re, acessamos a propriedade result para pegar 
               //o resultado e usamos o método toString() para garantir que 
              //nosso resultado seja uma string
              //Tendo certeza que nosso resultado agora já é uma JSON string, 
              //aplicamos a função JSON.decode para transformar nossa JSON string 
             //em objetos nativos do Action Script
                var jo:Object = JSON.decode(re.result.toString()); 
                //Agora que nosso resultado já está contido em objetos 
                //nativos Action Script criamos um Array usando var arr:Array
                
                //dado nosso resultado
                // {"result":[[{"CODIGO":"1","NOME":"FELIPE DOS SANTOS"},
                {"CODIGO":"2","NOME":"MARCELO FARIA"},
                {"CODIGO":"3","NOME":"PAULO MACHADO"},
                {"CODIGO":"4","NOME":"RODRIGO VIEIRA"}]]}
                
                //Em seguida acessamos o objeto jo fazendo uso de jo['result'] para pegar 
                //o valor da chave result, ou seja, pegamos do par o valor da chave result
                //que irá resultar o array abaixo:
                //[[{"CODIGO":"1","NOME":"FELIPE DOS SANTOS"},
                     {"CODIGO":"2","NOME":"MARCELO FARIA"},
                     {"CODIGO":"3","NOME":"PAULO MACHADO"},
                     {"CODIGO":"4","NOME":"RODRIGO VIEIRA"}]]
                
                //Como o valor da chave result é um array que tem dentro dele um 
                //só elemento que também é array
                //fazendo uso de [0] estamos dizendo que queremos pegar o 
                //primeiro elemento de nosso array
                //que irá resultar o array abaixo:
                //[{"CODIGO":"1","NOME":"FELIPE DOS SANTOS"},
                    {"CODIGO":"2","NOME":"MARCELO FARIA"},
                    {"CODIGO":"3","NOME":"PAULO MACHADO"},
                    {"CODIGO":"4","NOME":"RODRIGO VIEIRA"}]
                //pronto, o array acima será então atribuído para arr
                
                var arr:Array = jo['result'][0]; 
                
                var dp:ArrayCollection = new ArrayCollection(arr); 
                 //Neste ponto transformamos nosso array arr em um ArrayCollection. Motivo:
                //os DataGrid do Flex parecem trabalhar melhor com ArrayCollection
                
                DataGrid.dataProvider = dp; 
                //finalmente passamos os dados para o provedor de dados do DataGrid
                
                //Considerações aqui no flex
                //devemos ter em mente que cada elemento do array é uma linha no DataGrid
                //e que cada par de um objeto forma uma coluna, ou seja, vários pares 
                //formam várias colunas, donde podemos concluir
                //que um objeto equivale a um registro ou a uma instância de uma 
                //classe que pode ter 1 ou N Fields (campos)
            }
        ]]>
    </fx:Script>
    <fx:Declarations>
        <!-- Place non-visual elements (e.g., services, value objects) here -->
    </fx:Declarations>
    <s:TextInput x="11" y="4" width="184" id="txt_consulta" /> 
    <s:Button x="196" y="5" label="Consultar" width="117" click="Consultar()"/>
    <mx:DataGrid x="11" y="34" id="DataGrid" width="302">
        <mx:columns>
            <mx:DataGridColumn headerText="CODIGO" 
               dataField="CODIGO" width="100"/>
            <mx:DataGridColumn headerText="NOME" dataField="NOME" width="300"/>
        </mx:columns>
    </mx:DataGrid>

</s:Application>

Salve tudo (Ctrl + Shift + S).

OBS. Deixe executando o servidor

Execute o projeto flex: use o ícone Run ou o menu Run ou pressione (Ctrl + F11)

O resultado deverá ser parecido com o da imagem abaixo:

resultado

Abraço e até a próxima