Utilizando callback em DataSnap 2010
Solicitação número 1 dos usuários de DataSnap, suporte a callback, DataSnap 2010 permite a execução de server methods utilizando callback, em outras palavras, é esperar que o servidor envie retornos a aplicação cliente durante o processamento. Para exemplicar melhor, imagine os famosos fechamentos de final do mês, estes são disparados a partir de uma aplicação cliente que somente recebe um retorno ao finalizar o processo do lado servidor, com callback podemos notificar a aplicação cliente como está o processamento do lado servidor.
A classe TDBXCallback é responsável pelo callback, assim você deverá criar uma classe descendente, implementar o método execute e passar como parâmetro no seu server method. O servidor irá executar o método Execute do parâmetro de callback enviado ao servidor, na verdade o servidor está notificando o cliente para executar algum código.
Para melhor exemplificar, vamos imaginar que você precisa fazer o backup da sua base de dados a partir de uma instrução enviada pela aplicação cliente para o servidor, durante o processo de backup você deseja saber como está o andamento do backup, esta é uma tarefa para o callback, o código faz exatamento isso, backup de uma base de dados InterBase e retorna o log para a aplicação cliente.
Para começar temos que implementar o server method que será responsável por executar o backup, este obrigatoriamente necessita um parâmetro do tipo TDBXCallback o qual será responsável por enviar a notificação a aplicação cliente através do método Execute.
O método Execute por sua vez recebe envia um TJSONObject o qual contém um TJSONPair com as mensagens do log de backup da base de dados, lembre-se que eu optei por enviar apenas um valor dentro do objeto e a cada linha de log recebida o cliente será notificado que há uma mensagem nova.
procedure TDSServerBatch.StartBackup(sMessage: TDBXCallback;
sBackupFileName: String);
var
LCallbackValue: TJSONObject;
db: String;
begin
db := DMServerContainer.GetEmployeeDBName;
srvBackup.DatabaseName := Copy(db, Pos(':', db) + 1, Length(db));
srvBackup.Attach;
srvBackup.BackupFile.Add(sBackupFileName);
srvBackup.ServiceStart;
if srvBackup.Verbose then
while not srvBackup.Eof do
begin
// if srvBackup.IsServiceRunning then
begin
LCallbackValue := TJSONObject.Create;
LCallbackValue.AddPair(TJSONPair.Create('Server return',
srvBackup.GetNextLine));
sMessage.Execute(LCallbackValue);
end;
end;
if srvBackup.Active then
srvBackup.Detach();
end;
Vamos agora ao lado cliente, como temos que passar um parâmetro do tipo TDBXCallback então teremos que criar e implementar a tal classe. Vem a pergunta, para cada server method que necessita efetuar callback terei que criar uma classe de callback? A resposta é não, neste exemplo utilizaremos anonymous method para evitar isso.
Abaixo a classe de callback que estarei utilizando, veja que o método execute recebe um parâmetro do tipo TDSCallbackMethod o qual é um anonymous method, desta forma na criação da instância desta classe será passado o código a ser executando quando o servidor executar o método Execute.
type
TDSCallbackMethod = reference to function(const Args: TJSONValue): TJSONValue;
TMessageCallback = class(TDBXCallback)
private
FCallBackMethod: TDSCallbackMethod;
public
constructor Create(CallBackMethod: TDSCallbackMethod);
function Execute(const Arg: TJSONValue): TJSONValue; override;
end;
implementation
constructor TMessageCallback.Create(CallBackMethod: TDSCallbackMethod);
begin
FCallBackMethod := CallBackMethod;
end;
function TMessageCallback.Execute(const Arg: TJSONValue): TJSONValue;
begin
Result := FCallbackMethod(Arg);
end;
Com a classe de callback definida, temos agora que implementar o anonymous method e executar o server method conforme o exemplo a seguir.
Veja que o parâmetro Args do anonymous method é do tipo TJSONValue, extraimos os valores TJSONPair onde se encontra o log do backup.
var
s : TDSServerBatchClient;
begin
callback := TMessageCallback.Create( function(const Args: TJSONValue) : TJSONValue
var
LJSONObject: TJSONObject; I: Integer;
LMessage: string;
begin
// Extract information about the transformation from Json
LJSONObject := TJSONObject(Args);
Result := nil;
for I := 0 to LJSONObject.Size - 1 do begin
with LJSONObject.Get(I) do
LMessage := LMessage + Format('%s ==>> "%s"', [JSonString.Value, JsonValue.Value]);
// Display information in a listbox
MMBackupLog.Lines.Add(LMessage);
MMBackupLog.Update;
Result := TJSONTrue.Create;
end;
end);
Na sequência apenas executamos o método, passando a classe callback com parâmetro e o anonymous method será responsável por adicionar a mensagem de retorno no campo memo que está na tela, utilizado neste exemplo.
s := TDSServerBatchClient.Create(DMClientContainer.MyDSServer.DBXConnection); s.StartBackup(callback, 'mybackup.ibk');
Espero que este post tenha esclarecido as dúvidas relacionadas a callback.
Download do código fonte.










Developer Network
0 Comments
You can be the first one to leave a comment.