Uma alternativa interessante para criação de aplicações multicamadas sem DataSnap: RemoteDB.
Tenho pesquisado formas de conexão com banco de dados alternativas que possam nos tirar um pouco do convencional, nesta postagem vou abordar o RemoteDB da TMS.
RemoteDB e seu funcionamento
O RemoteDB é um conjunto de componentes da TMS Software que permite a criação de aplicações 3 camadas, possibilitando à aplicação cliente executar instruções SQL através de um Servidor HTTP, tornando-o uma fácil alternativa para converter aplicações cliente/servidor em aplicações de 3 camadas.
Resumidamente temos na camada servidora você utiliza FireDac, dbExpress, dbGO (ADO) ou outra suportada pelo Delphi e acessa esta camada servidor através de HTTP.
Download e algumas considerações
O RemoteDB não é adquirido separadamente, na verdade a TMS tem como estratégia a venda do componente num pacote chamado TMS Business Subscription, que contém 9 componentes ao todo. Vamos baixar a versão trial do pacote e nos ater apenas a criação de uma aplicação 3 camadas utilizando os componentes necessários para tal. Utilize o link abaixo:
TMS Business Pack Trial – Delphi XE7
A instalação deve ser feita ao melhor estilo Avançar até Concluir. Ao final do processo teremos novos itens na Paleta de Componentes do Delphi XE7.
Agora vamos à prática… vamos ao Delphi!
Nota: A versão Trial do TMS RemoteDB requer a aplicação do hotfix for FireMonkey apps on Android 5.0 (Lollipop) no seu Delphi XE7 para compilar aplicativos Android.
Criando o servidor HTTP para Conexão
Nosso primeiro passo será a criação de uma aplicação VCL simples que será transformada no Servidor HTTP. Vamos abrir o Delphi XE7 e criar um Nova Aplicação VCL (File-> New-> Other-> Delphi Projects-> VCL Application).
Vamos inserir no formulário 2 TButtons e 1 SQLConnection, estou optando aqui utilização do DBExpress, mas como já foi mencionado anteriormente você poderia ter optado por qualquer mecanismo (engine) de acesso a dados suportado pelo Delphi XE7. Veja mais informações na seção Adapters – Componentes de Acesso mais abaixo.
Altere o nome do formulário para frmServerTMS e configure os componentes e suas respectivas propriedades como segue:
- Button1
- Caption-> Iniciar Servidor
- Button2
- Caption -> Finalizar Servidor
O SQLConnection1 você deve configurar uma conexão DBExpress para um banco de dados qualquer que você tenha na sua máquina ou rede. No meu caso, vou apontar para o MS SQLServer que tenho aqui na minha rede.
Basicamente nossa aplicação servidora terá a seguinte aparência:
Adapters para cada Engine uma Adaptação
Basicamente esses componentes são os responsáveis por adaptar o componente de conexão da Engine de Acesso a Dados escolhida para um IDBConnection que é o componente de conexão do RemoteDB. Logo para cada mecanismo de acesso a dados teremos um Adapter específico declarado como Namespace em RemoteDB.Drivers.
Feitas introdução e considerações pontuais, vamos iniciar a seção de códigos!No nosso caso específico vamos trabalhar com o conjunto Adapter relativo ao DBExpress.
Codificando o Servidor HTTP
Nota: Os componentes que tornam possível o Servidor HTTP não são visuais, na minha opinião uma falha de estratégia da TMS pois poderia deixar o processo mais intuitivo e mais vendável, este foi inclusive um ponto debatido com um dos responsáveis pelo RemoteDB, podemos ter o Server visual em futuras versões após essa nossa conversa.
Precisaremos declarar algumas Units e variáveis, então vamos direto ao ponto. Nossa Seção Interface ficará aproximadamente assim:
interface uses ... RemoteDB.Drivers.dbExpress, RemoteDB.Client.Database, Sparkle.HttpSys.Server, RemoteDB.Drivers.Base, RemoteDB.Drivers.Interfaces, RemoteDB.Server.Module, ... type TfrmServerTMS = class(TForm) SQLConnection1: TSQLConnection; Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); private { Private declarations } function CreateNewIDBConnection: IDBConnection; public { Public declarations } end; var frmServerTMS: TfrmServerTMS; Module: TRemoteDBModule; Server: THttpSysServer; implementation
Posicione o cursor do teclado sobre a linha:
function CreateNewIDBConnection: IDBConnection;
e pressione no seu teclado a combinação Shift+Ctrl+C ou dê um Ctrl+Click para abrir a implementação da função, a mesma deve ficar assim:
implementation {$R *.dfm} { TfrmServerTMS } function TfrmServerTMS.CreateNewIDBConnection: IDBConnection; begin { Caso opte por configurar a conexão com o banco de dados em Tempo de Execução adicione o código aqui} Result := TDBExpressConnectionAdapter.Create(SQLConnection1, true); end;
Com isso já temos pronto todo o processo necessário para o nosso servidor funcionar. Vamos agora codificar os eventos OnClick em cada um dos botões que irão Iniciar e Finalizar o servidor:
procedure TfrmServerTMS.Button1Click(Sender: TObject); begin Server := THttpSysServer.Create; Module := TRemoteDBModule.Create('http://localhost:2001/tms/business/remotedb', TDBConnectionFactory.Create( function: IDBConnection begin Result := CreateNewIDBConnection; end )); Server.AddModule(Module); if not Server.IsRunning then begin Server.Start; frmServerTMS.Caption := 'Server TMS - Ativado' end; end;
Basicamente no Button1 instanciamos os objetos Module e Server que foram declarados anteriormente como variáveis na Seção Interface. Repare que o método de criação do Module (TRemoteDBModule) utiliza um endereço base no qual as aplicações clientes deverão conectar-se e um Método Anônimo contendo a função CreateNewIDBConnection que faz a utilização do Adapter configurando o SQLConnection1 devidamente conectado com o banco de dados (vale lembrar que este processo poderia ser feito via código em tempo de execução).
Algumas propriedades do TRemoteDBModule como devem ser mencionadas:
property UserName : string; property Password : string; property InstanceTimeout: integer;
Até aqui temos já podemos iniciar o servidor, vamos então ao código do botão responsável por finalizá-lo:
procedure TfrmServerTMS.Button2Click(Sender: TObject); begin if Server.IsRunning then begin Server.Stop; frmServerTMS.Caption := 'Server TMS - Desativado' end; Server.Free; end;
Vamos executar o servidor e conferir o resultado:
Agora que já temos o Servidor HTTP que irá nos prover a conexão de dados rodando. Vamos à aplicação cliente.
Criando o Client
Vamos criar uma aplicação Multi-Device no Delphi XE7 como já fizemos várias vezes. Nele vamos inserir 1 Button, 1 ListView e 1 Toobar e ajustaremos suas propriedades como abaixo:
- Button1
- Align -> Bottom
- Text -> Conectar
- ToolBar1
- Align -> Top
- ListView1
- Align -> Client
Agora vamos conhecer os componentes do lado cliente que fazem parte da suíte do RemoteDB:
TRemoteDB é o componente capaz de fazer com que o lado cliente conecte com o lado servidor, processo definido através das propriedades ServerUri, UserName, Password, Connected.
TXDataSet é o componente capaz de fazer toda manipulação de dados provenientes da conexão com o RemoteDB.
Vamos inserir um TRemoteDB em nossa aplicação cliente, e para níveis didáticos vamos apenas nos certificar que a propriedade ServerUri esteja apontando corretamente para o endereço de nosso TRemoteDBModule definido em nossa aplicação servidor, em nosso caso: http://192.168.0.16:2001/tms/business/remotedb, como as propriedades UserName e Password também não foram alterados e permanecerão com seus valores default: remotedb e business respectivamente.
Nota: Repare que na aplicação cliente configurei a propriedade ServerUri com o endereço IP da máquina servidora na minha rede (ip: 192.168.0.16), assim terei a possibilidade de acessá-la de outro dispositivo na rede como faremos adiante com um dispositivo Android.
Vamos inserir também o TXDataSet entretanto suas propriedades serão setadas apenas em tempo de execução, mais especificamente no clique do botão.
Ao final da configuração teremos uma tela semelhante à imagem abaixo:
Funcionamento e codificação da Aplicação Cliente
Basicamente temos o seguinte ao clicar sobre o botão os dados serão carregados para tela. Então vamos codificar o evento onClick do botão:
procedure TForm1.Button1Click(Sender: TObject); var i : integer; lvItem : TListViewItem; begin try XDataset1.Close; XDataset1.SQL.Add('select COD_PRODUTO, DESCR_PRODUTO from IMS_CADPRODUTO ' + 'where DESCR_PRODUTO like ' + QuotedStr('ATENOLOL%')); XDataset1.Open; XDataset1.First; ListView1.BeginUpdate; ListView1.Items.Clear; for i := 0 to XDataset1.RecordCount -1 do begin lvItem := ListView1.Items.AddItem(); lvItem.Text := XDataset1.Fields[1].AsString; XDataset1.Next; end; ListView1.EndUpdate; finally XDataset1.Free; end; end;
Feita a codificação da aplicação cliente vamos executar os programas e conferir o resultado. Vale lembrar que o código de nossa aplicação cliente pode ser executado tanto em plataforma Windows como em Android sem nenhuma alteração.
Nota: Ao executar a aplicação cliente de outra máquina que não seja a mesma da Aplicação Servidora, é necessário a liberação da porta utilizada nos FireWall's da máquina servidora, ou até mesmo a desativação dele para que seja possível a conexão por parte da aplicação cliente.
Lembrando que você precisa executar o Servidor e ativá-lo no botão ativar. Em seguida execute o cliente e clique sobre o botão para conectar e recuperar os dados. Veja as imagens abaixo:
Conclusão
Como mencionei a proposta da postagem é trazer alternativas ao convencional que já temos no Delphi. O pacote do RemoteDB da TMS é um caso dessas alternativas, cabe um estudo mais detalhado. Alguns projetos podem ser beneficiados com um ganho de tempo no que diz respeito a disponibilizar os dados na “nuvem” com essa possibilidade do Servidor HTTP. Testes de disponibilidade com uma maior atividade no servidor são necessários bem como outros pontos precisam ser analisados, mas não resta dúvidas que trata-se de uma boa alternativa principalmente para projetos já existentes que precisem ter seus dados disponibilizados. Uma boa lida na documentação é imprescindível!
Nota: O hotfix for FireMonkey apps on Android 5.0 (Lollipop) tem por objetivo corrigir problemas em aplicações FireMonkey Android em que Matrizes de dados de serem executadas entre código Nativo e Java Android API. Os sintomas mais visíveis desse problema eram imagens armazenadas no Delphi/FireMonkey não sendo exibidas em dispositivos Android 5.0 (Lollipop) e podiam terminar a aplicação inesperadamente. O mesmo é valido para dados enviados de um DataSet por exemplo. Veja a imagem abaixo de uma exceção gerada pela aplicação Android compilada sem a aplicação do HotFix:
Fico por aqui, até a próxima e bons códigos!
Referencia: TMS RemoteDB Documentation