Customers frequently ask us how to migrate from their legacy system to take full advantage of the advanced features in Data Abstract. Eugeny just finished a wiki article covering the ever popular move from DataSnap to Data Abstract. There is even a test case with source code to download. So pull out your legacy DataSnap applications and give them the upgrade you need so you can take advantage of all the great features of Data Abstract. I think you’ll be surprised how easy the migration can be, and happy you made the move!


This legacy DataSnap server uses authentication, provides access to the Customer table from Employee.gdb and allows to call custom server methods. So the migrated Data Abstract server will contain two services: the LoginService that will check authentication and the DataService that will be the main service.

Creating Server.RODL in Service Builder

This can be done via RemObjects SDK->Turn the server into a RemObjects SDK Server

After confirmation, [Service Builder]( "Service Builder") will be launched. For correct work, these two services should be created as descendants of base DataAbstract services. For this, DataAbstract4.RODL should be imported into server.RODL:
[![SB UseExistingRODL DataAbstract.png](](
After this, two new services should be created: the Loginservice with SimpleLoginService as the ancestor and the DataService with DataAbstractService as the ancestor. Also create two operations in DataService:
function EchoString(Value:WideString):WideString;function ReverseString(Value:WideString):WideString;
[![SB server rodl.png](](
Close [Service Builder]( "Service Builder").

Generation of files from RODL

Call RemObjects SDK->Regenerate Units from RODL. These files will be generated:

  • NewLibrary_Intf.pas
  • NewLibrary_Invk.pas
  • LoginService_Impl.pas
  • DataService_Impl.pas


Create a new datamodule and drop to it:

Set this value in the Object Inspector:

DAConnectionManager1.DriverManager= DADriverManager1
Click on ROIndyHTTPServer1.Dispatchers in the ObjectInspector and add a new dispatcher.
[![ROIndyHTTPServer BinDispatcher.png](](
Also create an onCreate event:
procedure TDataModule1.DataModuleCreate(Sender:TObject);begin ROIndyHTTPServer1.Active:=True;end;
## LoginService_Impl.pas

Select LoginService_Impl.pas.

Add ServerDataModule into the uses section and set

LoginService.SessionManager= ServerDM.ROInMemorySessionManager1.
in the Object Inspector. Two events are required in this unit:

procedure TLoginService.SimpleLoginServiceLogin(Sender:TObject; aUserID, aPassword: UTF8String; out aUserInfo: UserInfo;var aLoginSuccessful:Boolean);begin aLoginSuccessful :=(aUserID <;>;'')and(aUserID = aPassword);if aLoginSuccessful then CreateSession;end;   procedure TLoginService.SimpleLoginServiceLogout(Sender:TObject);begin DestroySession;end;
## DataService_Impl.pas

Select DataService_Impl.pas, drop

and set these properties in the ObjectInspector:

DataService.ServiceDataStreamer= DABin2DataStreamer1 DataService.ServiceSchema= DASchema1 DataService.SessionManager= ServerDM.ROInMemorySessionManager1 DataService.RequiresSession=True DASchema1.ConnectionManager= ServerDM.DAConnectionManager1
Copy the content of these methods from ServerMethodsUnit1.pas:
function TDataService.EchoString(const Value: UnicodeString): UnicodeString;begin Result := Value;end;   function TDataService.ReverseString(const Value: UnicodeString): UnicodeString;begin Result := StrUtils.ReverseString(Value);end;
Double-click on DASchema1 and [Schema Modeler]( "Schema Modeler") will be launched.

Create a new connection to Employee.gdb and the CUSTOMER table:

[![DASM IBX Customer.png](](
Close [Schema Modeler]( "Schema Modeler").

Compile and launch the server.

The server side is ready now.


The client side contains the login/logout buttons, a grid that shows a table and two buttons that call custom server methods.

Select client.dpr and add NewLibrary_Intf.pas from the server project to the client.dpr


Add a new datamodule.


and set these properties in the Object Inspector:

ROWinInetHTTPChannel1.TargetURL= http://localhost:8099/bin RORemoteService1.Channel= ROWinInetHTTPChannel1 RORemoteService1.Message= ROBinMessage1 RORemoteService1.ServiceName= DataService DARemoteDataAdapter1.DataStreamer= DABin2DataStreamer1 DARemoteDataAdapter1.RemoteService= RORemoteService1 DARemoteDataAdapter1.ReconcileProvider= DAVCLReconcileProvider1
Click on “Create Data Tables…” in the popup menu of DARemoteDataAdapter1. The Login Screen will be shown. Type *UserID=test;Password=test* in aLoginString and create the CUSTOMERS table in the next dialog.


Add NewLibrary_intf and ClientDataModule into the uses section. Replace the old methods in the MainForm:

procedure TForm2.Button1Click(Sender:TObject);begin DataModule1.tbl_CUSTOMER.Close; DataModule1.tbl_CUSTOMER.Open;end;   procedure TForm2.Button2Click(Sender:TObject);begin DataModule1.tbl_CUSTOMER.ApplyUpdates;end;   procedure TForm2.Button3Click(Sender:TObject);begin ShowMessage((DataModule1.RORemoteService1as IDataService).EchoString(Edit3.Text));end;   procedure TForm2.Button4Click(Sender:TObject);begin ShowMessage((DataModule1.RORemoteService1as IDataService).ReverseString(Edit3.Text));end;   procedure TForm2.Button5Click(Sender:TObject);beginifnot CoLoginService.Create(DataModule1.ROBinMessage1,DataModule1.ROWinInetHTTPChannel1).LoginEx(UTF8Encode(Format('UserID=%s;Password=%s',[Edit1.Text,Edit2.Text])))then showMessage('Problems with login');end;   procedure TForm2.Button6Click(Sender:TObject);begin DataModule1.tbl_CUSTOMER.Close; CoLoginService.Create(DataModule1.ROBinMessage1,DataModule1.ROWinInetHTTPChannel1).Logout;end;
And the client side is ready.

P.S.: Don’t forget to remove the old datasnap units from projects.