Delphi Programming Guide
Delphi Programmer 

Menu  Table of contents
Bookmark and Share

Part I - Foundations
  Chapter 1 Delphi 7 and Its IDE
  Chapter 2 The Delphi Programming Language
  Chapter 3 The Run-Time Library
  Chapter 4 Core Library classes
  Chapter 5 Visual Controls
  Chapter 6 Building the User Interface
  Chapter 7 Working with Forms
Part II - Delphi Object-Oriented Architectures
  Chapter 8 The Architecture of Delphi Applications
  Chapter 9 Writing Delphi Components
  Chapter 10 Libraries and Packages
  Chapter 11 Modeling and OOP Programming (with ModelMaker)
  Chapter 12 From COM to COM+
Part III - Delphi Database-Oriented Architectures
  Chapter 13 Delphi's Database Architecture
  Chapter 14 Client/Server with dbExpress
  Chapter 15 Working with ADO
  Chapter 16 Multitier DataSnap Applications
  Chapter 17 Writing Database Components
  Chapter 18 Reporting with Rave
Part IV - Delphi, the Internet, and a .NET Preview
  Chapter 19 Internet Programming: Sockets and Indy
  Chapter 20 Web Programming with WebBroker and WebSnap
  Chapter 21 Web Programming with IntraWeb
  Chapter 22 Using XML Technologies
  Chapter 23 Web Services and SOAP
  Chapter 24 The Microsoft .NET Architecture from the Delphi Perspective
  Chapter 25 Delphi for .NET Preview: The Language and the RTL
       
  Appendix A Extra Delphi Tools by the Author
  Appendix B Extra Delphi Tools from Other Sources
  Appendix C Free Companion Books on Delphi
       
  Index    
  List of Figures    
  List of tables    
  List of Listings    
  List of Sidebars  

 
Previous Section Next Section

DataSnap over SOAP

Now that you have a reasonably good idea how to build a SOAP server and a SOAP client, let's look at how to use this technology in building a multitier DataSnap application. You'll use a Soap Server Data Module to create the new web service and the SoapConnection component to connect a client application to it.

Building the DataSnap SOAP Server

Let's look at the server side first. Go to the Web Services page of the New Items dialog box and use the Soap Server Application icon to create a new web service, and then use the Soap Server Data Module icon to add a DataSnap server-side data module to the SOAP server. I did this in the SoapDataServer7 example (which uses the Web App Debugger architecture for testing purposes). From this point on, all you do is write a normal DataSnap server (or a middle-tier DataSnap application), as discussed in Chapter 16 ("Multitier DataSnap Applications"). In this case, I added InterBase access to the program by means of dbExpress, resulting in the following structure:

object SoapTestDm: TSoapTestDm
  object SQLConnection1: TSQLConnection
    ConnectionName = 'IBLocal'
  end
  object SQLDataSet1: TSQLDataSet
    SQLConnection = SQLConnection1
    CommandText = 'select * from EMPLOYEE'
  end
  object DataSetProvider1: TDataSetProvider
    DataSet = SQLDataSet1
  end
end

The data module built for a SOAP-based DataSnap server defines a custom interface (so you can add methods to it) inheriting from IAppServerSOAP, which is defined as a published interface (even though it doesn't inherit from IInvokable).

Tip 

Delphi 6 used DataSnap's standard IAppServer interface for exposing data via SOAP. Delphi 7 has replaced the default with the inherited IAppServerSOAP interface, which is functionally identical but allows the system to discriminate the type of call depending on the interface name. You'll see shortly how to call an older application from a client built in Delphi 7, because this process is not automatic.

The implementation class, TSoapTestDm, is the data module, as in other DataSnap servers. Here is the code Delphi generated, with the addition of the custom method:

type
  ISampleDataModule = interface(IAppServerSOAP)
    ['{D47A293F-4024-4690-9915-8A68CB273D39}']
    function GetRecordCount: Integer; stdcall;
  end;
   
  TSampleDataModule = class(TSoapDataModule, ISampleDataModule,
      IAppServerSOAP, IAppServer)
    DataSetProvider1: TDataSetProvider;
    SQLConnection1: TSQLConnection;
    SQLDataSet1: TSQLDataSet;
  public
    function GetRecordCount: Integer; stdcall;
  end;

The base TSoapDataModule doesn't inherit from TInvokableClass. This is not a problem as long as you provide an extra factory procedure to create the object (which is what TInvokableClass does for you) and add it to the registration code (as discussed earlier, in the section "Exposing an Existing Class as a Web Service"):

procedure TSampleDataModuleCreateInstance(out obj: TObject);
begin
  obj := TSampleDataModule.Create(nil);
end;
   
initialization
  InvRegistry.RegisterInvokableClass(
    TSampleDataModule, TSampleDataModuleCreateInstance);
  InvRegistry.RegisterInterface(TypeInfo(ISampleDataModule));

The server application also publishes the IAppServerSOAP and IAppServer interfaces, thanks to the (little) code in the SOAPMidas unit. As a comparison, you can find a SOAP DataSnap server built with Delphi 6 in the SoapDataServer folder. The example can still be compiled in Delphi 7 and works fine, but you should write new programs using the structure of the newer; an example is in the SoapDataServer7 folder.

Tip 

Web service applications in Delphi 7 can include more than one SOAP data module. To identify a specific SOAP data module, use the SOAPServerIID property of the SoapConnection component or add the data module interface name to the end of the URL.

The server has a custom method (the Delphi 6 version of the program also had one, but it never worked) that uses a query with the select count(*) from EMPLOYEE SQL statement:

function TSampleDataModule.GetRecordCount: Integer;
begin
  // read in the record count by running a query
  SQLDataSet2.Open;
  Result := SQLDataSet2.Fields[0].AsInteger;
  SQLDataSet2.Close;
end;

Building the DataSnap SOAP Client

To build the client application, called SoapDataClient7, I began with a plain program and added a SoapConnection component to it (from the Web Services page of the palette), hooking it to the URL of the DataSnap web service and referring to the specific interface I'm looking for:

object SoapConnection1: TSoapConnection
  URL = 'http://localhost:1024/SoapDataServer7.soapdataserver/' +
    'soap/Isampledatamodule'
  SOAPServerIID = 'IAppServerSOAP - {C99F4735-D6D2-495C-8CA2-E53E5A439E61}'
  UseSOAPAdapter = False
end

Notice the last property, UseSOAPAdapter, which indicates you are working against a server built with Delphi 7. As a comparison, the SoapDataClient (again, no 7) example, which uses a server created with Delphi 6 and recompiled with Delphi 7, must have this property set to True. This value forces the program to use the plain IAppServer interface instead of the new IAppServerSOAP interface.

From this point on, you proceed as usual, adding a ClientDataSet component, a DataSource, and a DBGrid to the program; choosing the only available provider for the client dataset; and hooking the rest. Not surprisingly, for this simple example, the client application has little custom code: a single call to open the connection when a button is clicked (to avoid startup errors) and an ApplyUpdates call to send changes back to the database.

SOAP versus Other DataSnap Connections

Regardless of the apparent similarity of this program to all the other DataSnap client and server programs built in Chapter 16, there is a very important difference worth underlining: The SoapDataServer and SoapDataClient programs do not use COM to expose or call the IAppServerSOAP interface. Quite the opposite—the socket- and HTTP-based connections of DataSnap still rely on local COM objects and a registration of the server in the Windows Registry. The native SOAP-based support, however, allows for a totally custom solution that's independent of COM and that offers many more chances to be ported to other operating systems. (You can recompile this server in Kylix, but not the programs built in Chapter 16.)

The client program can also call the custom method I've added to the server to return the record count. This method could be used in a real-world application to show only a limited number of records but inform the user how many haven't yet been downloaded from the server. The client code to call the method relies on an extra HTTPRIO component:

procedure TFormSDC.Button3Click(Sender: TObject);
var
  SoapData: ISampleDataModule;
begin
  SoapData := HttpRio1 as ISampleDataModule;
  ShowMessage (IntToStr (SoapData.GetRecordCount));
end;

 
Previous Section Next Section


 


 


Copyright © 2004-2018 "Delphi Sources". Delphi Programming Guide
   Facebook     Twitter