Delphi 6 Update 2 and higher (including Delphi 7 and Delphi 2005) offer a special Service Activation Model option when creating new SOAP Server Interfaces.
The Service Activation Model can be set to Per Request or Global.
The default value is Per Request, which means that for every incoming client request, a new instance of the SOAP object will be created (and destroyed after use).
|
|
When the value is set to Global, it means that only one global SOAP object will be used to handle incoming requests.
I've had some experience with this option in C++Builder 6, and it works like a charm: adding and registering a special Factory function in case of the Global service activation mode.
Imagine my surprise when I found that this option has absolutely no effect when using in Delphi 6.02 or Delphi 7 (or Delphi 2005 for that matter)!
The same (Per Request) code is generated, regardless of the value of the Service Activation Model option.
Also, the on-line help for Delphi 6 (or higher) has no information about this dialog either (whereas C++Builder 6 contains a page with helpful information).
Another little thing that was forgotten (or left unfinished) for Delphi?
It appears to be an oversight indeed, since consultation with a Borland engineer responsible for this area confirmed my suspicion: it was missed!
However, this engineer also told me that it was only the template that was missing this information - the actual code generating Wizard is the same for Delphi and C++Builder.
So he pointed me to the SoapWebServiceImpl.pas template in the Objrepos directory, in which I could make the required changes.
Looking at the code that was generated by C++Builder 6, I've decided to add the following snippet of code to the bottom of the SoapWebServiceImpl.pas file (replacing the original initialization section).
Warning: make a backup of the file SoapWebServiceImpl.pas before applying adding this snippet, and remember that you do this at your own risk (it appears to work for me):
[!if=(Activation, "GLOBAL")]
procedure [!InterfaceName]Factory(out obj: TObject);
{$J+}
const
iInstance: I[!InterfaceName] = nil;
instance: [!ImplClassName] = nil;
begin
if instance = nil then
begin
instance := [!ImplClassName].Create;
instance.GetInterface(I[!InterfaceName], iInstance)
end;
obj := instance
end;
[!endif]
initialization
[!if=(Comments, "TRUE")]
{ Invokable classes must be registered }
[!endif]
[!if=(Activation, "GLOBAL")]
InvRegistry.RegisterInvokableClass([!ImplClassName], [!InterfaceName]Factory);
[!else]
InvRegistry.RegisterInvokableClass([!ImplClassName]);
[!endif]
end.
After I've gone through all this trouble to update the SoapWebServiceImpl.pas template file, I decided to find out what the effect would be from using the Global setting compared to the Per Request setting.
For a CGI executable - my target - the difference is nothing, since the SOAP object will be created and destroyed with every incoming request (since each request will load and unload the CGI executable).
At least it will have an effect for ISAPI/NSAPI or Apache Shared Module DLLs.
In those cases, the Global Object setting will ensure that the WebService application uses only one instance of the SOAP object to handle all incoming requests, while the default Per Request setting creates a new SOAP object for every incoming request (freeing the object after the request is handled).
Before you modify SoapWebServiceImpl.pas (in the Objrepos directory) make sure you have a backup of the original file as well - just in case.
Note that anything you change in the "official" Delphi directory is "dangerous", since official patches from Borland will only patch original untouched files.