How to serialize a TList of objects with Delphi

Some weeks ago a customer asked to me if it is possibile serialize a TList of objects. “Hey, you should use a TObjectList for this”, I said, but he absolutely needs (I dont know why) of a TList.

This is the (simple) sample code tested with Delphi XE2 Update4. Enjoy.


unit Unit4;

interface

uses
  Winapi.Windows,
  Winapi.Messages,
  System.SysUtils,
  System.Variants,
  System.Classes,
  Vcl.Graphics,
  Vcl.Controls,
  Vcl.Forms,
  Vcl.Dialogs,
  Vcl.StdCtrls;

type
  TForm4 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TPerson = class
  private
    FName: String;
    procedure SetName(const Value: String);
  published
    property Name: String read FName write SetName;
  end;

var
  Form4: TForm4;

implementation


uses
  Contnrs,
  dbxjson,
  dbxjsonreflect;

{$R *.dfm}

procedure TForm4.Button1Click(Sender: TObject);
var
  list: TList;
  m: TJSONMarshal;
  json: TJSONObject;
  p1: TPerson;
  p2: TPerson;
begin
  p1 := TPerson.Create;
  p2 := TPerson.Create;
  try
    p1.Name := 'Daniele Teti';
    p2.Name := 'Peter Parker';
    list := TList.Create;
    try
      list.Add(p1);
      list.Add(p2);

      m := TJSONMarshal.Create;
      try
        // Register a specific converter for field FList
        m.RegisterConverter(TList, 'FList', function(Data: TObject; Field: String): TListOfObjects
          var
            l: TList;
            j: integer;
          begin
            l := Data as TList;
            SetLength(Result, l.Count);
            for j := 0 to l.Count - 1 do
              Result[j] := TObject(l[j]); // HardCast from pointer
          end);

        json := m.Marshal(list) as TJSONObject;
        try
          Memo1.Lines.Text := json.tostring;
        finally
          json.free;
        end;
      finally
        m.free;
      end;
    finally
      list.free;
    end;
  finally
    p1.free;
    p2.free;
  end;
end;

{ TPerson }

procedure TPerson.SetName(const Value: String);
begin
  FName := Value;
end;

end.

The output is, as expected, the following:

{"type":"System.Classes.TList","id":1,"fields":{"FList":[{"type":"Unit4.TPerson","id":2,"fields":{"FName":"Daniele Teti"}},{"type":"Unit4.TPerson","id":3,"fields":{"FName":"Peter Parker"}}],"FCount":2,"FCapacity":4}}

Duck Typing in Delphi

During a new dorm feature development, I’m faced a nice problem:

I want to have a generic access to a “kind” of list

Let’s say:

procedure DoSomething(Obj: TMyListType);
begin
...
end;

But, I want to have that generic access without a Layer Supertype object, because I need to be able to use objects from other libraries or 3rd party. In this case traditional polimorphism is not usable, so I’ve opted for an interface…

procedure DoSomething(MyIntf: IMyListInterface);
begin
...
end;

Cool, but I want to have that access without any change to that object. So implement an interface is not a viable solution. This is particulary true because the generics data structure in Delphi do not implement an interface. Will be nice to have a fully interfaced list and dictionaries in a future Delphi version.

So, how I could implement a generic access to a generic list?

procedure DoSomething(MySomething: ???);
begin
...
end;

However, operations on that list are few and well known, so I’ve opted for a “DuckTyping“.

Introducing the duck
Introducing the duck

The name of the concept refers to the duck test, attributed to James Whitcomb Riley, which may be phrased as follows:

“When I see a bird that walks like a duck and swims like a duck and quacks like a duck, I call that bird a duck.”

So, in my case, I’ve created an Adapter object wich adapts the external interface (few, well know operations) to the “duck” inside it.

The adapter is useful because I can use the compiler checking that the RAW RTTI access doesn’t allow.

Write an “RTTI adapter” using the new Delphi RTTI, is very simple. This is the code of the class TDuckTypedList that allow to use any object as a “list”. How I can define that the object is actually a list?

The criteria is:

If the object has
– An “Add” method with one parameter of type TObject (or descendant);
– A “Count” property;
– A “GetItem” method that have an integer parameter and return an object;
– A “Clear” method;
then, that object is a list.

So I can write the following:

DuckObject := TDuckTypedList.Create(Coll);  //the adapter
for x := 0 to DuckObject.Count - 1 do
  DoSomething(DuckObject.GetItem(x));  

I’ve done some speed tests comparing this way to the classic static way, and the speed is almost the same because the RTTI lookup is cached in the constructor of the adapter. So, so far so good.

This solution is already in use inside the dorm code in a feature branch.

Full code is available in the dorm SVN

Any comments?

dorm, “The Delphi ORM”, officially published at ITDevCon

As all the attendees have seen, at the last ITDevCon, I’ve officially published dorm as an OpenSource project.

dorm, The Delphi ORM
dorm, The Delphi ORM

You can find the project on google code: http://code.google.com/p/delphi-orm/

An introduction to dorm is available on google docs.

dorm begins as a my personal project more than one year ago, and now is sponsored by bitTime Software that offers custom development, consultancy, mentoring and so on.

Why dorm?

These are my personal reasons of because I’ve started to write dorm:
I WANT an ORM for Delphi… but:
I dont want (or I cant) change my database
I want persistence ignorance
I want to access to the «metal»
I want to persist PODO
I don’t hate SQL, but I know that 90% of it is boilerplate and errors prone

First example

Insert and retrieve object with dorm
Insert and retrieve object with dorm

 

You can persist anything you want.
bitTime actively use dorm, so it’s continuosly updated and evolved.

Repeat, you can find the project on google code and an introduction to dorm is available on google docs.

Let me know what do you think about.

Do you need an ORM like dorm in Delphi?

ITDevCon 2011, recap

Last Friday ended the third edition of ITDevCon, the European Conference on Delphi and its related technologies.
ITDevCon this year was even bigger and funny.
There have been more present, more sponsors, more speakers, more topics and a lot of people with the desire to learn new things and improve their every day work.

A special thanks goes to all the speakers who participated and the sponsors who have contributed their support to make this conference a major event for the European community Delphi.

I hope that the content and the organization is liked to you at least half of how much it is liked to me.
We are organizing slides, videos and examples for each speech to put it all on-line available to participants at the conference as soon as possible. You will receive an email informing you of how to download all the material available.
In the coming days, on the conference website (www.itdevcon.it) we will post all the pictures we have done in these three days.

If you have any photos that you want to see published, send them to me, we’ll publish it on the official website.

Some friends (and speakers) already blogged about the conference:

DavidI
http://blogs.embarcadero.com/davidi/2011/10/24/41413

Paweł Głowacki
http://blogs.embarcadero.com/pawelglowacki/2011/10/30/39392

Primoz Gabrijelcic
http://www.thedelphigeek.com/2011/10/itdevcon-2011recap.html

Marco Cantù
http://blog.marcocantu.com/blog/itdevcon2011_summary.html

And now, Daniele Teti :-)

ASAP I’ll publish the slides of every speeches.

If you want to see the tweet about the conference, you can go here.

Here’s some photos from the conference.

During the “Country Evening” some of us have been singing with the good “Tex Roses” friend (an italian country band). Probably there are at least 15 video documenting my “performance”!

Here’s the video recorded by Primož (the Delphi Geek)

I thank again all those who have spoken and all those who have attended to ITDevCon.
See you next year.

– Daniele

App Android ITDevCon2011 disponibile sul Market (ITALIAN)

Manca solo una settima all’inizio di ITDevCon2011. Per permettere a tutti gli iscritti (e far decidere chi è ancora indeciso) di sfruttare al meglio i due giorni di intensa formazione, abbiamo appena pubblicato l’applicazione ITDevCON2011 sul’Android Market.
Trevete il programma completo della conferenza, i profili degli speaker e informazioni sugli sponsor.
Inoltre, potrete definire i vostri speech preferiti in modo da essere avvisati subito prima dell’inizio dello speech.
Potrete votare e commentare ogni speech. Potete commentare da subito inserendo le vostre aspettative per lo speech o alcune delucidazioni sul contenuto. Il voto invece sarà possibile solo a speech avvenuto.

Dal punto di vista tecnico, questa applicazione Android utilizza un servizio REST scritto con Delphi utilizzando DataSnap e i Mobile DataSnap connectors per Android.
Per chi fosse interessato al “Making”, durante la conferenza potrà assistere allo speech di Salvatore Sparacino che illustrerà i vari step dello sviluppo e le soluzioni tecnologiche adottate.
Per definire il vostro profilo, votare e commentare, dovrete utilizzare il codice fornito al momento dell’iscrizione. Se non siete partecipanti, o ancora non vi è arrivato il codice di accesso, potete utilizzare l’applicazione come “anomymous”. In questo caso non potrete salvare i vostri speech preferiti Né votare o commentare.

Dashboard

La time table
Speaker details
Dettagli dello speaker (in questo screenshot, DavidI)

Il link da dove installare l’applicazione è il seguente:
https://market.android.com/details?id=it.bittime.itdevcon2011

Happy ITDevCon2011

ITDevCon2011 Android App

In less that a week, ITDevCon2011 will begin. To allow all members (and to let decide who is still undecided) to take advantage of the two days of intense training, we have just published the application ITDevCON2011 on the Android Market. You’ll find full conference program, speaker profiles and information about the sponsors.
In addition, you can define your favorite speeches in order to be alerted immediately before the start of the speech.

You can vote and comment every speech. You can comment now by entering your expectations for the speech or some clarifications on the content. The vote, however, is allow only after the speech.
From a technical standpoint, this Android application uses a Delphi DataSnap REST service and the DataSnap Mobile Connectors for Android.

For those interested in the “Application Making Of” during the conference may attend the speech of Salvatore Sparacino illustrating the various steps of development and the technological solutions adopted. Very cool! Salvatore will talk about a REAL app, not only a demo!

To define your training profile, add rates and comments, you have to use the code provided at registration. If you’ll not attend, or you have not received your access code, you can use the application as “anomymous.” In this case, you cannot save your favorite speeches or votes or comments.

Dashboard

The time table
Speaker details
Speaker details (here DavidI)

The link to install the application is as follows:
https://market.android.com/details?id=it.bittime.itdevcon2011

Happy ITDevCon2011!

DataSnap Mobile Connectors in RAD Studio XE2

WARNING! I’ve been authorized by EMBARCADERO to write about RAD Studio XE2.

RAD Studio XE2 is full of nice and exciting features. One of the most interesting IMHO is the DataSnap extension called “Mobile Connectors”.

In the past, I’ve talked about connecting and using your datasnap REST service with Android, creating ad-hoc json messages and manually parsing the returned json messages. With RAD Studio XE2 this is no longer needed. If you have a DataSnap REST service, you can automatically generate the proxy connector for the major mobile platforms. Yes, just like you have been doing with Delphi or C++ since Delphi 2010.

DataSnap XE2 version supports 4 mobile platforms:

  • Android (Using Java)
  • BlackBerry (Using Java)
  • Windows Phone (Using C#)
  • iOS 4.2 (Using ObjectiveC)

If you want to enable your DataSnap server for the Mobile Connectors you have to explicitely check the feature in the “New DataSnap Server” wizard.

The generated proxies support all the standard Delphi types and maps them to the native target language. Some of the most used Delphi types (e.g. TStream, TDBXReader and so on) have been rewritten in the target language to allows a greater compatibility and a simpler programming interface. The functionalities of the various Delphi classes are not-one-to-one with the Delphi version, but  similar.

From a remote (or local) machine you can download the generated proxy and all the required files using a tool called “Win32ProxyDownloader.exe” which is in the bin folder of your RAD Studio installation. In my FieldTest version, this tool called without parameters, shows its help.

As usual you should have the RAD Studio bin folder in your PATH environment variable, so you can change your current directory to where you want the proxy and write this command in a commandprompt window:

Win32ProxyDownloader -language java_android -host localhost:8080

The proxy and all the needed files are ready in the current directory.

Mat DeLong wrote a very nice Eclipse plugin to use the proxy downloader directly from Android or BlackBerry development environment. You can find this plugin here.

You know that Android is my preferred mobile platform, don’t you?

So, let’s go with an Android example.

To use the generated java proxy, in an Android client application I can write something like this:

//Create the connection
connection = new DSRESTConnection();
connection.setHost("10.0.0.2");
connection.setPort(8080);
connection.setProtocol("http");
//Create the proxy
proxy = new DSProxy.TServerMethods1(connection);
//Use a simple remote method
int sum = proxy.Sum(1,4));
//Use a complex remote method
TStream inStream = null;
TStream outStream = null;
String s = "abc";
inStream = new TStream(s.getBytes());
outStream = proxy.DoSomethigWithATStream(inStream, sum, "Hello DataSnap Mobile Connectors");
//here I can use the java TStream type

All the custom Delphi types (e.g. TPerson) are mapped on the target platform as TJSONObject. All the TJSONValue hierarchy has been ported, with a very similar interface, to the target platform as a wrapper of the native JSON classes.

So, you can write code as the following (Java on Android):

TJSONObject jobj = new TJSONObject();
jobj.addPairs("firstname", "Daniele");
jobj.addPairs("lastname", "Teti");
jobj.addPairs("age", 31);
jobj.addPairs(new TJSONPair("nickname", new TJSONString("Spiderman")));
if (jobj.has("firstname"))
  doSomethingWithFirstName(jobj.getString("firstname"));
doSomethingWithAge(jobj.getDouble("age").intValue());

All the proxies work in a similar way except for the Windows Phone one. Indeed, the WP proxy is asynchronous because Microsoft does not allow a sinchronous http request in the main thread. All the proxies are thread safe.

The proxies are generated on the fly by a set of specialized writers. The TDSProxyGenerator component is in charge of generate the actual proxy code in the target language/platform using one of the specialized generators.

In the next figure you can see all the available proxy generators. Some of them are there since Delphi XE but all the mobile platforms have been added in XE2.

That’s all for now.

RAD Studio XE2 will be officially presented all over the world during the “RADStudio XE2 World Tour”.

You can find the list of all launch events in the RADStudio XE2 World Tour page.

I’ll be a presenter at 3 launch events in Italy and United Arab Emitates.

These are the events where I’ll be (click to register):

RAD Studio XE2 had a lot of new features. This is really the BEST ever Delphi version since version 1.

I’ll blog about other XE2 features mostly Delphi related (as usual) so stay tuned.