Utilizando callback em DataSnap 2010

 

DataSnap 2010 callbackSolicitaçã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.

Compartilhe e divirta-se:
  • Print
  • Twitter
  • Facebook
  • Yahoo! Bookmarks
  • Digg
  • Sphinn
  • del.icio.us
  • Mixx
  • Google Bookmarks
  • LinkedIn
  • Live

Tags:

 
 
 
 

0 Comments

 

You can be the first one to leave a comment.

 

Leave a Comment

 




XHTML: You can use these tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

 
 
 
Get Adobe Flash playerPlugin by wpburn.com wordpress themes