Delphi Tutorial


Introduction

All Apache Thrift tutorials require that you have:

  1. The Apache Thrift Compiler and Libraries, see Download and Building from Source for more details.
  2. Generated the tutorial.thrift and shared.thrift files:

    thrift -r --gen delphi tutorial.thrift
    
  3. Followed all prerequisites listed below.

Prerequisites

Client

program DelphiClient;

{$APPTYPE CONSOLE}
{$D 'Copyright (c) 2012 The Apache Software Foundation'}

uses
  SysUtils,
  Generics.Collections,
  Thrift in '..\..\..\lib\delphi\src\Thrift.pas',
  Thrift.Collections in '..\..\..\lib\delphi\src\Thrift.Collections.pas',
  Thrift.Exception in '..\..\..\lib\delphi\src\Thrift.Exception.pas',
  Thrift.Utils in '..\..\..\lib\delphi\src\Thrift.Utils.pas',
  Thrift.Stream in '..\..\..\lib\delphi\src\Thrift.Stream.pas',
  Thrift.Protocol in '..\..\..\lib\delphi\src\Thrift.Protocol.pas',
  Thrift.Server in '..\..\..\lib\delphi\src\Thrift.Server.pas',
  Thrift.Transport in '..\..\..\lib\delphi\src\Thrift.Transport.pas',
  Shared in '..\..\gen-delphi\Shared.pas',
  Tutorial in '..\..\gen-delphi\Tutorial.pas';


type
  DelphiTutorialClient = class
  public
    class procedure Main;
  end;


//--- DelphiTutorialClient ---------------------------------------


class procedure DelphiTutorialClient.Main;
var transport : ITransport;
    protocol  : IProtocol;
    client    : TCalculator.Iface;
    work      : IWork;
    sum, quotient, diff : Integer;
    log       : ISharedStruct;
begin
  try
    transport := TSocketImpl.Create( 'localhost', 9090);
    protocol  := TBinaryProtocolImpl.Create( transport);
    client    := TCalculator.TClient.Create( protocol);

    transport.Open;

    client.ping;
    WriteLn('ping()');

    sum := client.add( 1, 1);
    WriteLn( Format( '1+1=%d', [sum]));

    work := TWorkImpl.Create;

    work.Op   := TOperation.DIVIDE;
    work.Num1 := 1;
    work.Num2 := 0;
    try
      quotient := client.calculate(1, work);
      WriteLn( 'Whoa we can divide by 0');
      WriteLn( Format('1/0=%d',[quotient]));
    except
      on io: TInvalidOperation
      do WriteLn( 'Invalid operation: ' + io.Why);
    end;

    work.Op   := TOperation.SUBTRACT;
    work.Num1 := 15;
    work.Num2 := 10;
    try
      diff := client.calculate( 1, work);
      WriteLn( Format('15-10=%d', [diff]));
    except
      on io: TInvalidOperation
      do WriteLn( 'Invalid operation: ' + io.Why);
    end;

    log := client.getStruct(1);
    WriteLn( Format( 'Check log: %s', [log.Value]));

    transport.Close();

  except
    on e : Exception
    do WriteLn( e.ClassName+': '+e.Message);
  end;
end;


begin
  try
    DelphiTutorialClient.Main;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

Server

program DelphiServer;

{$APPTYPE CONSOLE}
{$D 'Copyright (c) 2012 The Apache Software Foundation'}

{$Q+}     // throws exceptions on numeric overflows

uses
  SysUtils,
  Generics.Collections,
  Thrift in '..\..\..\lib\delphi\src\Thrift.pas',
  Thrift.Collections in '..\..\..\lib\delphi\src\Thrift.Collections.pas',
  Thrift.Exception in '..\..\..\lib\delphi\src\Thrift.Exception.pas',
  Thrift.Utils in '..\..\..\lib\delphi\src\Thrift.Utils.pas',
  Thrift.Stream in '..\..\..\lib\delphi\src\Thrift.Stream.pas',
  Thrift.Protocol in '..\..\..\lib\delphi\src\Thrift.Protocol.pas',
  Thrift.Server in '..\..\..\lib\delphi\src\Thrift.Server.pas',
  Thrift.Transport in '..\..\..\lib\delphi\src\Thrift.Transport.pas',
  Shared in '..\..\gen-delphi\Shared.pas',
  Tutorial in '..\..\gen-delphi\Tutorial.pas';


type
  TCalculatorHandler = class( TInterfacedObject, TCalculator.Iface)
  protected
    FLog : TDictionary< Integer, ISharedStruct>;

    // TSharedService.Iface
    function  getStruct(key: Integer): ISharedStruct;

    // TCalculator.Iface
    procedure ping();
    function  add(num1: Integer; num2: Integer): Integer;
    function  calculate(logid: Integer; const w: IWork): Integer;
    procedure zip();

  public
    constructor Create;
    destructor Destroy;  override;

  end;

  DelphiTutorialServer = class
  public
    class procedure Main;
  end;


//--- TCalculatorHandler ---------------------------------------------------


constructor TCalculatorHandler.Create;
begin
  inherited Create;
  FLog := TDictionary< Integer, ISharedStruct>.Create();
end;


destructor TCalculatorHandler.Destroy;
begin
  try
    FreeAndNil( FLog);
  finally
    inherited Destroy;
  end;
end;


procedure TCalculatorHandler.ping;
begin
  WriteLn( 'ping()');
end;


function TCalculatorHandler.add(num1: Integer; num2: Integer): Integer;
begin
  WriteLn( Format( 'add( %d, %d)', [num1, num2]));
  result := num1 + num2;
end;


function TCalculatorHandler.calculate(logid: Integer; const w: IWork): Integer;
var entry : ISharedStruct;
begin
  try
    WriteLn( Format('calculate( %d, [%d,%d,%d])', [logid, Ord(w.Op), w.Num1, w.Num2]));

    case w.Op of
      TOperation.ADD      :  result := w.Num1 + w.Num2;
      TOperation.SUBTRACT :  result := w.Num1 - w.Num2;
      TOperation.MULTIPLY :  result := w.Num1 * w.Num2;
      TOperation.DIVIDE   :  result := Round( w.Num1 / w.Num2);
    else
      raise TInvalidOperation.Create( Ord(w.Op), 'Unknown operation');
    end;

  except
    on e:Thrift.TException do raise;  // let Thrift Exceptions pass through
    on e:Exception do raise TInvalidOperation.Create( Ord(w.Op), e.Message);  // repackage all other
  end;

  entry := TSharedStructImpl.Create;
  entry.Key   := logid;
  entry.Value := IntToStr( result);
  FLog.AddOrSetValue( logid, entry);
end;


function TCalculatorHandler.getStruct(key: Integer): ISharedStruct;
begin
  WriteLn( Format( 'getStruct(%d)', [key]));
  result := FLog[key];
end;


procedure TCalculatorHandler.zip;
begin
  WriteLn( 'zip()');
end;


//--- DelphiTutorialServer ----------------------------------------------------------------------


class procedure DelphiTutorialServer.Main;
var handler   : TCalculator.Iface;
    processor : IProcessor;
    transport : IServerTransport;
    server    : IServer;
begin
  try
    handler   := TCalculatorHandler.Create;
    processor := TCalculator.TProcessorImpl.Create( handler);
    transport := TServerSocketImpl.Create( 9090);
    server    := TSimpleServer.Create( processor, transport);

    WriteLn( 'Starting the server...');
    server.Serve();

  except
    on e: Exception do WriteLn( e.Message);
  end;

  WriteLn('done.');
end;


begin
  try
    DelphiTutorialServer.Main;
  except
    on E: Exception do
      Writeln(E.ClassName, ': ', E.Message);
  end;
end.

Additional Information