Integrando Delphi e Flex usando REST/JSON

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.

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

Os requisitos são:

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:

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:

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

Na unit Unit1:

Na unit ServerMethodsUnit1:

Na unit ServerContainerUnit1:

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:

Clique em OK.

Na unit FrmPrincipal:

Selecione o componente SQLConnection1:

Selecione o SQLDataSet1:

SELECT * FROM CONTATOS WHERE NOME LIKE :PNOME

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

Selecione a Unit uSMContato:

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:

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:

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:

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:

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.

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:

Abraço e até a próxima

Artigos relacionados