Writing a DataSnap server and an iOS client in 10 minutes flat!

By: Anders Ohlsson

Abstract: This article shows you how you can easily create your first DataSnap server and connect to it from your iPhone or iPad. We will be using Delphi XE2, FireMonkey and InterBase.

    Our goal

The goal of this article is to:

1. Create a Delphi XE2 DataSnap server that connects to InterBase XE and serves up our data, complete with blobs.

2. Create a Delphi XE2 FireMonkey iOS client that uses the auto-created mobile DataSnap connector for iOS to get the data from the DataSnap server and display it as per the below screenshot:

Hide image
iOS Simulator Screen shot Mar 21, 2012 5

    Writing the DataSnap server

We will start by creating a DataSnap server by selecting File | New | Other | Delphi Projects | DataSnap Server | DataSnap REST Application.

Hide image
Click to see full-sized image

We go through the expert and select Stand-Alone VCL application in this case:

Hide image
Click to see full-sized image

We then select a port and test it:

Hide image
Click to see full-sized image

On the next screen we simply go with the defaults (sample methods and sample web files) for simplicity. Also check Mobile Connectors and Server Module:

Hide image
Click to see full-sized image

On the next screen we'll pick TDataModule as the ancestor:

Hide image
Click to see full-sized image

We then finish up and save the project as FishServer.dproj somewhere on disk.

    Adding our business logic

Now we need to add a useful methods that implements our business logic. In this case we will provide a single method to return a TDataSet - let's call it GetDataSet.

Go to the Data Explorer and expand the IBCONNECTION. If you already have it pointed at the dbdemos.gdb sample database file, it will look like this:

Hide image
Click to see full-sized image

Below is a the Modify Connection dialog if you need to set up your IBCONNECTION:

Hide image

We're now ready to drag the BIOLIFE table over to our ServerMethodsUnit1. When we drop it down, we get a TSQLConnection and a TSQLDataSet:

Hide image
Module

The TSQLConnection and the TSQLDataSet will have the following parameters set, respectively. Notice that we changed the CommandText and the CommandType to limit the result set in our example.

Hide image
Conn Hide image
Table

Here's the declaration of our server methods class. Notice our GetDataSet method.

type
  TServerMethods1 = class(TDataModule)
    IBCONNECTION: TSQLConnection;
    BIOLIFE: TSQLDataSet;
  private
    { Private declarations }
  public
    { Public declarations }
    function GetDataSet: TDataSet;
  end;

The implementation of GetDataSet is very simple as follows:

function TServerMethods1.GetDataSet: TDataSet;
begin
  BioLife.Open;
  Result := BioLife;
end;

That's it! The server is done.

    Writing the iOS client

Now, on to writing the iOS client that will talk to our server. We create a new FireMonkey HD application for iOS. The only UI element we add in this example is a TTreeView.

Hide image
Click to see full-sized image

We need to add all the proxy files to the project to make it easy for us. Below, a screen shot of the Project Explorer after adding the proxy files:

Hide image
Click to see full-sized image

The actual code to get the data from the DataSnap server and display it in our TTreeView will all be in our Form's OnCreate method:

procedure TForm2.FormCreate(Sender: TObject);
var
  Conn  : TDSRESTConnection;
  Proxy : TServerMethods1;
  DS    : TDataSet;
  S     : TStream;
  Item  : TTreeViewItem;
  Img   : TImage;
begin
  Conn := TDSRESTConnection.Create(nil);
  Conn.Host := '10.20.10.6';
  Conn.Port := 8080;
  Conn.Protocol := 'http';
  Proxy := TServerMethods1.Create(Conn);

  DS := Proxy.GetDataSet;
  while not DS.EOF do begin
    Item := TTreeViewItem.Create(Self);
    Item.Height := 80;
    Item.Font.Size := 18;
    Item.Text := DS.FieldByName('Common_Name').AsString;
    TreeView1.AddObject(Item);

    Img := TImage.Create(Self);
    Img.Parent := Item;
    Img.Align := TAlignLayout.alRight;
    Img.Width := 128;

    S := ExtractBitmapIntoStream(DS.FieldByName('Graphic') as TBlobField);
    Img.Bitmap.LoadFromStream(S);
    S.Free;

    DS.Next;
  end;

  Proxy.Free;
  Conn.Free;
end;

Let's break this one down. We first create a connection to our DataSnap REST server and create the mobile connector proxy for our server methods:

Conn := TDSRESTConnection.Create(nil);
Conn.Host := '10.20.10.6';
Conn.Port := 8080;
Conn.Protocol := 'http';
Proxy := TServerMethods1.Create(Conn);

We then call the GetDataSet server method:

DS := Proxy.GetDataSet;

Next we loop over all returned records in the dataset. For each one we create a new item in the treeview. Each item will display the common name of the fish, and display its image in a TImage. We create all these components on the fly:

Item := TTreeViewItem.Create(Self);
Item.Height := 80;
Item.Font.Size := 18;
Item.Text := DS.FieldByName('Common_Name').AsString;
TreeView1.AddObject(Item);

Img := TImage.Create(Self);
Img.Parent := Item;
Img.Align := TAlignLayout.alRight;
Img.Width := 128;

S := ExtractBitmapIntoStream(DS.FieldByName('Graphic') as TBlobField);
Img.Bitmap.LoadFromStream(S);
S.Free;

We implement the ExtractBitmapIntoStream helper function as:

function ExtractBitmapIntoStream(BlobField : TBlobField) : TStream;
var
  S1, S2 : TStream;
begin
  S1 := TMemoryStream.Create;
  S2 := TMemoryStream.Create;
  BlobField.SaveToStream(S1);
  S1.Position := 8;
  S2.CopyFrom(S1,S1.Size-8);
  Result := S2;
end;

The above method reads copies everything except the first 8 bytes (a header that we need to discard) into a new stream, and returns just the stream with the bitmap in it. Special thanks to my colleague David Powell for letting me know about the extraneous 8-byte header that needs to be discarded.

    Compiling the client

Once the client is created. We run dpr2xcode to generate the extra information needed for Xcode. We then open the project in XCode.

    Testing the client

Screen shot of iOS client running in the simulator:

Hide image
iOS Simulator Screen shot Mar 21, 2012 5

    Resources

Download the whole project (server and client) from here:

http://cc.embarcadero.com/item/28786

    Contact

Please feel free to email me with feedback to aohlsson at embarcadero dot com.

Server Response from: ETNASC01