Migrating from a DataSnap application to Data Abstract (Delphi)
In this article will be shown how to migrate from Datasnap applications to DataAbstract application.
Server-side
This datasnap server uses authentication, provides access to Customer
table from Employee.gdb
and allows to call custom server methods.
so DataAbstract server will contain two services: LoginService that will check authentication and DataService that will be main service.
Creating Server.RODL in Service Builder
It can be made via Remoting SDK & Data Abstract->Turn server into a Remoting SDK Server (RODL Based)
after confirmation, Service Builder will be launched.
For correct work, these two services should be created as descendants of base Data Abstract services. For this, DataAbstract4.RODL
should be imported into server.RODL:
After this, two new services should be created: Loginservice
with SimpleLoginService
as the ancestor and DataService
with DataAbstractService
as the ancestor. Also create two operations in DataService:
function EchoString(Value: WideString): WideString;
function ReverseString(Value: WideString): WideString;
Close Service Builder.
Generation of files from RODL
Call Remoting SDK & Data Abstract->Regenerate Units from RODL
.
These files will be generated:
- NewLibrary_Intf.pas
- NewLibrary_Invk.pas
- LoginService_Impl.pas
- DataService_Impl.pas
ServerDataModule.pas
Create a new datamodule and drop to it:
- TROIndyHTTPServer
- TROBinMessage
- TROInMemorySessionManager
- TDADriverManager
- TDAConnectionManager
- TDAIBXDriver
set this value in Object Inspector: DAConnectionManager1.DriverManager = DADriverManager1 Click on ROIndyHTTPServer1.Dispatchers in ObjectInspector and add new dispatcher
procedure TDataModule1.DataModuleCreate(Sender: TObject);
begin
ROIndyHTTPServer1.Active := True;
end;
LoginService_Impl.pas
Select LoginService_Impl.pas.
Add ServerDataModule
into uses section and set in Object Inspector:
LoginService.SessionManager = ServerDM.ROInMemorySessionManager1.
Two events are required in this unit:
procedure TLoginService.SimpleLoginServiceLogin(Sender: TObject; aUserID,
aPassword: String; 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
set properties in ObjectInsector:
DataService.ServiceDataStreamer = DABin2DataStreamer1
DataService.ServiceSchema = DASchema1
DataService.SessionManager = ServerDM.ROInMemorySessionManager1
DataService.RequiresSession = True
DASchema1.ConnectionManager = ServerDM.DAConnectionManager1
copy 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;
Dbl click on DASchema1, Schema Modeler will be launched.
create a new connection to Employee.gdb
and CUSTOMER
table:
Close Schema Modeler.
Compile and launch server.
Server-side is ready now.
Client-side
Client side contains login/logout buttons, grid that shows table and two buttons which call custom servers methods.
Select client.dpr and add NewLibrary_Intf.pas from server project to client.dpr
ClientDataModule.pas
Add a new datamodule via wizard (New->Other->Data Abstract->Client module for VCL application
) or perform some actions manually, like:
Drop
- TROWinInetHTTPChannel
- TROBinMessage
- TRORemoteService
- TDARemoteDataAdapter
- TDABin2DataStreamer
- TDAVCLReconcileProvider
and set properties in 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 popup menu of DARemoteDataAdapter1.
Login Screen will be shown, type UserID=test;Password=test
in aLoginString and create CUSTOMERS table in next dialog.
MainForm.pas
Add NewLibrary_intf and ClientDataModule into uses section. Replace old methods in 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.RORemoteService1 as IDataService).EchoString(Edit3.Text));
end;
procedure TForm2.Button4Click(Sender: TObject);
begin
ShowMessage((DataModule1.RORemoteService1 as IDataService).ReverseString(Edit3.Text));
end;
procedure TForm2.Button5Click(Sender: TObject);
begin
if not 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;
Client side is ready.
P.S. Don't forget to remove old datasnap units from projects