Delphi 7 Indy Standalone Web Services/SOAP Server



Creating MySOAPServer.exe (a standalone web service app).
Step by step instructions -- Delphi 7 Enterprise Edition.

This app uses Indy IdHTTPWebBrokerBridge from Indy 9 which is included in Delphi 7 Enterprise Edition to create a standalone SOAP Web Service application (i.e., No web server such as Apache or IIS necessary.)

Copy the two files:
       IdHTTPWebBrokerBridge.pas
       IdCompilerDefines.inc
   from the Delphi7\Source\Indy directory into your local project directory.

Do a File --> New --> Other,
   Select the WebServices tab.
   Then select the SOAP Server Application icon, and then click on OK.

   From the New SOAP Server Application window,
   Select the Web App Debugger executable radio button.
   In the Class Name field enter: Dummy

   From the Confirm window, which asks Create Interface for SOAP Module?,
   click on Yes.

   From the Add New WebService window,
   Enter Service Name: MySOAPWebService
   (it will automatically fill in the Unit Identifier with the same value.)
   Then click on OK.

Do a View --> Project Manager,
   Expand the Project(n).exe folder.
   Highlight the MySOAPWebServiceImpl.pas entry and press the [Delete] key.
   In the Confirm window, which asks Remove MySOAPWebServiceImpl.pas?,
   click on Yes.
   In the next Confirm window,
   which asks Save changes to MySOAPWebServiceImpl.pas?,
   click on No. (the Impl.pas is not needed.)

Do a View --> Project Manager,
   Expand the Unit1 folder.
   Double-click on the Unit1.pas entry.
   Remove the initialization section as that code is not needed:

  initialization
    TWebAppSockObjectFactory.Create('Dummy');

Do a View --> Project Manager,
   Double-click on the Form1 entry.
   Press the [F11] key for the Object Inspector.
   Change the Name property to MySOAPServerForm (from Form1).

Do a View --> Project Manager,
   Expand the Unit2 folder.
   Double-click on the WebModule2 entry.
   Press the [F11] key for the Object Inspector.
   Change the Name property to MyWebModule (from WebModule2).

Do a View --> Project Manager,
   Double-click on the Unit2.pas entry.
   In the initialization section, check for a nil before assigning a value to the
      WebRequestHandler.WebModuleClass property.

  initialization
    if WebRequestHandler <> nil then
      WebRequestHandler.WebModuleClass := TMyWebModule;

Do a File --> New --> Other,
   Select the WebServices tab.
   Then select the SOAP Server Data Module icon, and then click on OK.
   In the Soap Data Module Wizard window,
   enter Module Name: MyAppServerSoapDataModule

Do a View --> Project Manager,
   Expand the Unit3 folder.
   Double-click on the Unit3.pas entry.
   Add MySOAPWebServiceIntf to the uses clause in the interface section.

  uses
    SysUtils, Classes, InvokeRegistry, Midas, SOAPMidas, SOAPDm,
    MySOAPWebServiceIntf;

   Add IMySOAPWebService as an ancestorClass in the the TMyAppServerSoapDM declaration.

    TMyAppServerSoapDataModule = class(TSoapDataModule,
      IMyAppServerSoapDataModule, IAppServerSOAP, IAppServer,
      IMySOAPWebService)
   [Note that there is not a semicolon line terminater after this line.]

Do a View --> Project Manager,
   Double-click on the Unit1.pas entry.
   Add IdHTTPWebBrokerBridge to the uses clause in the interface section.

  uses
    SysUtils, Classes, Forms, IdHTTPWebBrokerBridge;
   Add the private variable FWebBrokerBridge to the TForm1 declaration.
    private
      FWebBrokerBridge: TIdHTTPWebBrokerBridge;
Add Unit2 to the uses clause in the implementation section.
  uses
    SockApp, Unit2;

Do a View --> Project Manager,
   Double-click on the MySOAPServerForm entry.
   Press the [F11] key for the Object Inspector.
   Select the Events tab.
   Double-click on the OnCreate event.
   Add the following code in the FormCreate procedure.

  // Create server.
  FWebBrokerBridge := TIdHTTPWebBrokerBridge.Create(Self);

  // Register web module class.
  FWebBrokerBridge.RegisterWebModuleClass(TMyWebModule);

  // Set default port.
  FWebBrokerBridge.DefaultPort := 1024;

  // Start server.
  FWebBrokerBridge.Active := True;
   Press the [F11] key for the Object Inspector.
   Double-click on the OnDestroy event.
   Add the following code in the FormDestroy procedure.
  // Stop server.
  FWebBrokerBridge.Active := False;

  // Free server component.
  FreeAndNil(FWebBrokerBridge);
At this point you should be able to run the app, which will listen on port 1024 for SOAP requests.

You may test that it is working by opening the following in IE:
   
http://localhost:1024/wsdl/IMySOAPWebService
   Internet Explorer (5.5 or higher?) is apparently the only browser in which this will work.
   Other browsers such as Mozilla, Netscape, Opera, etc, will not display the XML document properly.

Next are the instructions for adding a SOAP operation (web service)
to the MySOAPServer SOAP web server app.

Do a View --> Project Manager,    Double-click on the Unit3.pas entry.
   Add the public function declaration for the webservice in the
   declaration for TMyAppServerSoapDataModule (in the interface section.)

  public
    function HelloWorld(Param1: string): string; stdcall;
   Add the public function definition for the webservice in the
implementation of TMyAppServerSoapDataModule
  { TMyAppServerSoapDataModule }

  function TMyAppServerSoapDataModule.HelloWorld(Param1:
    string): string; stdcall;
  begin
    Result := 'Hello World.  Your data: ' + Param1;
  end;
Do a View --> Project Manager,
   Double-click on the MySOAPWebServiceIntf.pas entry.
   Add the function interface for the webservice to the
   declaration for IMySOAPWebService (in the interface section.)
    IMySOAPWebService = interface(IInvokable)
    ['{4BF42BCF-294B-4D28-93D8-8311FA8B190E}']
      function HelloWorld(Param1: string): string; stdcall;
    end;
And optionally, rename and save the files:
Do a File --> Save Project As,
   In the Save Unit1 As window,
   Enter File Name: MySOAPServerFormU.pas

   In the Save Unit2 As window,
   Enter File Name: MyWebModuleU.pas

   In the Save MySOAPWebServiceIntf window,
   Enter File Name: MySOAPWebServiceIntf.pas

   In the Save Unit3 As window,
   Enter File Name: MyAppServerSoapDataModuleU.pas

   In the Save Project(n) As window,
   Enter File Name: MySOAPServer.dpr

Do a View --> Project Manager,
   Expand the MySOAPServerFormU folder,
   Double-click on the MyFormU.pas entry.
   Change the reference Unit2 to MyWebModuleU.

  uses
    SockApp,
    MyWebModuleU;
Do a File --> Save

Now you should be able to run the app again, which will listen on port 1024 for SOAP requests.



Creating MySOAPClient.exe (an application to consume a web service.)
Step by step instructions -- Delphi 7 Enterprise Edition.

Make sure the MySOAPServer.exe created earlier is running before continuing.

   Confirm by opening the following in IE:
      
http://localhost:1024/wsdl/IMySOAPWebService

Do a File --> New --> Application,
   Drop a Button (from Standard Toolbar) onto the form.
   Drop a Label (from Standard Toolbar) onto the form.
   Drop an HTTPRIO (from the WebServices Toolbar) onto the form.

   Arrange the Button1 and Label1 objects
   (i.e., widen the label a bit and move the objects so that the form looks pretty.)

Do a View --> Project Manager,
   Expand the Project(n).exe folder.
   Expand the Unit1 folder.
   Double-click on the Form1 entry.
   Press the [F11] key for the object Inspector.
   Change the Name property to MySOAPClientForm (from Form1).

Do a File --> New --> Other,
   Select the WebServices tab,
   Select the WSDL Importer icon and click on OK.

   In the WSDL Import Wizard window,
   Enter the Location of WSDL File or URL:
       http://localhost:1024/wsdl/IMySOAPWebService
   Then click on Next and then click on Finish.

Do a View --> Project Manager,
   Double-click on the Unit1.pas entry.
   Add IMySOAPWebService1 to the uses clause in the interface section.

  uses
     Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
     Dialogs, IMySOAPWebService1;
Do a View --> Project Manager,
   Double-click on the MySOAPClientForm entry.
   Select the HTTPRIO1 object.    Press the [F11] key for the Object Inspector.
   For the WSDLLocation property select from the dropdown:
       http://localhost:1024/wsdl/IMySOAPWebService
   For the Service property select from the dropdown:
       IMySOAPWebServiceservice
   For the Port property select from the dropdown:
       IMySOAPWebServicePort

Do a View --> Project Manager,
   Double-click on the MySOAPClientForm entry.
   Double-click on the Button1 object.
   In the Button1Click procedure, enter:

  begin
    Label1.Caption :=
      (HTTPRIO1 as IMYSOAPWebService).HelloWorld('Worked!');
  end;
And optionally, rename and save the files:
Do a File --> Save Project As,
   In the Save Unit1 As window,
   Enter File Name: MySOAPClientFormU.pas

   In the Save IMySOAPWebService1 As window,
   Enter File Name: MySOAPWebServiceClientIntf.pas

   In the Save Project1 As window,
   Enter File Name: MySOAPClient.dpr

Do a View --> Project Manager,    Expand the MySOAPClientForm folder,
   Double-click on the MySOAPClientFormU.pas entry.
   Change the reference IMySOAPWebService1 to MySOAPWebServiceClientIntf.

  uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, MySOAPWebServiceClientIntf, InvokeRegistry, Rio, SOAPHTTPClient,
    StdCtrls;

Do a File --> Save.

Now you should be able to run the application and click on Button1 which will consume the web service.



Creating MySOAPService.exe (an NT Service).
Step by step instructions -- Delphi 7 Enterprise Edition.

First create and build the MySOAPServer project as shown above because source files from that project will be needed for the MySOAPService project. Then you may continue on with the following instructions.

Do a File --> New --> Other,
   Select the New tab.
   Then select the Service Application icon,
   and then click on OK.

   From the Service1 window,
   Press the [F11] key for the Object Inspector.
   Select the Properties tab.
   Change the Name property to MyService (from Service1).

Do a Project --> Add To Project,
   select the file MyWebModuleU.pas and click on OK.

Do a Project --> Add To Project,
   select the file MySOAPWebServiceIntf.pas and click on OK.

Do a Project --> Add To Project,
   select the file MyAppServerSoapDataModuleU.pas and click on OK.

Do a View --> Project Manager,
   Expand the Project(n).exe folder.
   Expand the Unit1 folder.
   Double-click on the Unit1.pas entry.

   Add IdHTTPWebBrokerBridge to the uses clause in the interface section.

  uses
    Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs,
    IdHTTPWebBrokerBridge;
   Add the private variable FWebBrokerBridge to the TService1 declaration.
  private
    FWebBrokerBridge: TIdHTTPWebBrokerBridge;
   Add MyWebModuleU to the uses clause in the implementation section.
  {$R *.DFM}
  uses
    MyWebModuleU;
Do a View --> Project Manager,
   Double-click on the MyService entry.
   Press the [F11] key for the Object Inspector.
   Select the Events tab.
   Double-click on the OnStart event.
   Add the following code in the ServiceStart procedure.
  // Create server.
  FWebBrokerBridge := TIdHTTPWebBrokerBridge.Create(Self);

  // Register web module class.
  FWebBrokerBridge.RegisterWebModuleClass(TMyWebModule);

  // Set default port.
  FWebBrokerBridge.DefaultPort := 1024;

  // Start server.
  FWebBrokerBridge.Active := True;
   Press the [F11] key for the Object Inspector.
   Double-click on the OnStop event.
   Add the following code in the ServiceStop procedure.
  // Stop server.
  FWebBrokerBridge.Active := False;

  // Free server component.
  FreeAndNil(FWebBrokerBridge);
Do a File --> Save Project As,
   In the Save Unit1 As window,
   Enter File Name: MyServiceU.pas

   In the Save Project(n) As window,
   Enter File Name: MySOAPService.dpr

Do a Project --> Build MySOAPService.

To Register the service
(i.e., to add the service to the Windows system registry)
Do a Run --> Parameters,
   In the Parameters field, enter: /install
   and then click on OK.

Do a Run --> Run.
(Should show an Information window stating Service installed successfully.)
   Click on OK.

Do a Run --> Parameters,    Clear the Parameters field,
   then click on OK.

   Press the [Ctrl-Shift-S] key combination to Save All.

To start the service, open the service window.
   If Windows NT 4,
      Start --> Settings --> Control Panel --> Services
   If Windows 2000,
      Start --> Settings --> Control Panel --> Administrative Tools --> Services

The MySOAPServer.exe created earlier uses the same port as this NT service will,
so close MySOAPServer.exe if it is still running.

Then select MyService and press the Start Service button.
(The Start Service Button looks like the play button of an audio device.)



Forcing Delphi to use Indy Library for SOAP

Reportedly there are problems with wininet.dll, when your NT service is stressed.
You can improve this by specifying that the Indy library is used for the SOAP server calls.

I haven't run into the issue myself but am reposting what was initially found in a post in the borland.public.delphi.webservices.soap newsgroup by Martijn Houtman.

> (using a tip from Robert Maclean):
>
> 1- Add the following to the library path:
>    $(DELPHI)\Source\Soap
> 2 - Open \Source\Soap\SoapHTTPTrans.pas,
>     and make a backup of it!
> 3 - Line 13 should currently read:
>     //{$DEFINE USE_INDY}
> 4 - Remove the comment symbols to make it read
>     {$DEFINE USE_INDY}
> 5 - Rebuild your client side project
>     (clicking run won't work)
>
> This changes the behaviour of the SOAP client to
> use Indy and not the standard Windows setup,
> like it is done in Kylix. You can change it back
> later when the bugs are solved.





Please send corrections, clarifications, improvements or any other comments to delphisoap@digicoast.com