Delphi Tutorial


Introduction

All Apache Thrift tutorials require that you have:

  1. Built and installed the Apache Thrift Compiler and Libraries, see Building from source for more details.
  2. Generated the tutorial.thrift and shared.thrift files as discussed here.

    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.Console in '..\..\..\lib\delphi\src\Thrift.Console.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;
    Console.WriteLine('ping()');

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

    work := TWorkImpl.Create;

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

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

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

    transport.Close();

  except
    on e : Exception
    do Console.WriteLine( 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.Console in '..\..\..\lib\delphi\src\Thrift.Console.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
  Console.WriteLine( 'ping()');
end;


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


function TCalculatorHandler.calculate(logid: Integer; const w: IWork): Integer;
var entry : ISharedStruct;
begin
  try
    Console.WriteLine( 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
  Console.WriteLine( Format( 'getStruct(%d)', [key]));
  result := FLog[key];
end;


procedure TCalculatorHandler.zip;
begin
  Console.WriteLine( '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);

    Console.WriteLine( 'Starting the server...');
    server.Serve();

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

  Console.WriteLine('done.');
end;


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

Additional Information