Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DataSnap Rest Server windows Service

i'm try to building a DataSnap Rest Application running as a windows service, but the wizard just have "Stand-alone VCL application", "Stand-alone console application" and "ISAPI dynamic link library"(i'm using Delphi XE2 enterprise). Someone can help me. Thanks.

like image 614
JoFan Avatar asked Oct 25 '12 10:10

JoFan


1 Answers

It would be more convenient if the DataSnap REST wizard had the option to create a Windows Service (how else would you run an application server?), but you can work around it with a little fiddling.

The first time I ran in to this, I created a regular DataSnap REST server as a VCL application and a regular Windows service and copied the relevant portions from the REST server to the service. Just make sure the output directory for the service is the same as the directory for the VCL application.

The service's .dpr might look like this:

program Service;

uses
  Vcl.SvcMgr,
  Web.WebReq,
  IdHTTPWebBrokerBridge,
  WebModuleUnit1 in '..\GUI\WebModuleUnit1.pas' {WebModule1: TWebModule},
  ServerMethodsUnit1 in '..\GUI\ServerMethodsUnit1.pas' {ServerMethods1: TDSServerModule},
  ServerContainerUnit1 in '..\GUI\ServerContainerUnit1.pas' {ServerContainer1: TDataModule},
  Unit1 in 'Unit1.pas' {Service1: TService};

{$R *.RES}

begin
  if not Application.DelayInitialize or Application.Installing then
    Application.Initialize;

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

  Application.CreateForm(TService1, Service1);
  Application.Run;
end.

The service's main unit might look like this:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Classes,
  Vcl.Graphics, Vcl.Controls, Vcl.SvcMgr, Vcl.Dialogs,
  IdHTTPWebBrokerBridge, Web.HTTPApp;

type
  TService1 = class(TService)
    procedure ServiceCreate(Sender: TObject);
    procedure ServiceExecute(Sender: TService);
    procedure ServiceStart(Sender: TService; var Started: Boolean);
    procedure ServiceStop(Sender: TService; var Stopped: Boolean);
  private
    FServer: TIdHTTPWebBrokerBridge;
    procedure TerminateThreads;
  public
    function GetServiceController: TServiceController; override;
  end;

var
  Service1: TService1;

implementation

{$R *.DFM}

uses
  //Datasnap.DSService;  // XE2
  Datasnap.DSSession;  // XE3

procedure ServiceController(CtrlCode: DWord); stdcall;
begin
  Service1.Controller(CtrlCode);
end;

{ TService1}

function TService1.GetServiceController: TServiceController;
begin
  Result := ServiceController;
end;

procedure TService1.ServiceCreate(Sender: TObject);
begin
  FServer := TIdHTTPWebBrokerBridge.Create(Self);
end;

procedure TService1.ServiceExecute(Sender: TService);
begin
  while not Terminated do
  begin
    Sleep(1000);
    ServiceThread.ProcessRequests(False);
  end;
end;

procedure TService1.ServiceStart(Sender: TService; var Started: Boolean);
begin
  if not FServer.Active then
  begin
    FServer.Bindings.Clear;
    FServer.DefaultPort := 8080;
    FServer.Active := True;
  end;
end;

procedure TService1.ServiceStop(Sender: TService; var Stopped: Boolean);
begin
  TerminateThreads;
  FServer.Active := False;
  FServer.Bindings.Clear;

  ServiceThread.Terminate;
end;

procedure TService1.TerminateThreads;
begin
  if TDSSessionManager.Instance <> nil then
    TDSSessionManager.Instance.TerminateAllSessions;
end;

end.
like image 177
Bruce McGee Avatar answered Oct 02 '22 08:10

Bruce McGee