Midware TServerObject.Execute

From Overbyte
Revision as of 14:15, 9 May 2011 by Marie (talk | contribs) (→‎Examples)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

Main page -> Midware component reference -> TServerObject -> Execute

Definition

procedure Execute; virtual;

Description

The ORB (Object Request Broker, TRequestBroker component) call Execute method to make the server object do his work: execute the request and produce a response. You MUST override this method and place the effective code for the server object work. A TServerObject without Execute method do nothing !

Execute method is one of the most important method of a TServerObject. In fact, it is often the only procedure you will write in your TServerObject. The overall performance for your server directly depends on the performance of this procedure. The best Execute method is one that execute almost instantaneously.

There are two design possibilities:

a) Execute method will do all the work that TServerObject has to do

b) Execute method will start processing and return immediately.

Option (b) can be split into two sub-options:

b1) Execute start an asynchonous (event driven) component or object

b2) Execute start a thread to do the job

While a TServerObject is executing his Execute method, no other object can be instanciated. Multitasking is almost down while Execute is executing. This is why you'd better do the work outside of the Execute method, using an asynchonous, event driven component or object, or a thread.

Once a TServerObject has finished his work, it must call Finish method to return data back to the client. If Finish is called from within Execute, it must be the last statement before returning from Execute. Using option (b) above, Finish is not called from Execute, but from thread termination code, or asynchonous component final event (often called OnRequestDone).

When Execute method gets control, parameters from client is received in the FRequestBuffer property. Most TServerObject retrieve parameters to know what to do. For example data to append to a database or key used to fetch data from database.

TServerObject has to produce an result set and an answer to return back to the client. Result set is to be stored in FResponseBuffer. Answer is to be stored in FResultStatus property. FResultStatus is a string. The value is never used by MidWare framework and is left to the application designer. But by convention it is often used like the FTP and HTTP protocols: FresultStatus begin by a number which gives some error code. Sample programs in MidWare package use '200' as a normal result, any other value being some kind of error.

Examples

The following sample is a trivial Execute method. It take no parameters and return a result set made of a single record with a single field:

<syntaxhighlight lang="delphi"> procedure TServerObjectHelloWorld.Execute; begin

   FResponseBuffer.WriteFields(TRUE, ['Hello World']);
   FResultStatus := '200';
   Finish;

end; </syntaxhighlight>

The following sample is an Execute method that convert input data (request parameters) to uppercase: <syntaxhighlight lang="delphi"> procedure TServerObjectUpperCase; var

   I : Integer;

begin

   // While loop to iterate thru all records
   while not FRequestBuffer.Eof do begin
       // For loop to iterate thru all fields
       for I := 0 to FRequestBuffer.FieldCount - 1 do
           FResponseBuffer.WriteFields(
                 I = 0,
                 [UpperCase(FRequestBuffer.Fields[I])]);
       FRequestBuffer.Next;
   end;
   FResultStatus := '200';
   Finish;

end; </syntaxhighlight>

Following sample use a TTable to access a database. TTable is dropped on server's main form and initialized by main server code. This is done for simplicity but it is not recommended because it make a TServerObject dependent upon a given server. See FUserData property for a recommended implementation. <syntaxhighlight lang="delphi"> procedure TServerObjectGETCLIENT.Execute; var

   UData : PUserDataRecord;
   Fld   : Integer;
   Key   : String;

begin

   CliTable.Active := TRUE;
   Key := UpperCase(FRequestBuffer.Fields[0]);
   CliTable.IndexName := 'LAST';
   CliTable.SetKey;
   CliTable.FieldByName('LAST').AsString := Key;
   if CliTable.GotoKey then begin
       // Data found
       FResultStatus := 200;
       // Copy all fields from the table to the response set
       for Fld := 0 to CliTable.FieldCount - 1 do
           FResponseBuffer.WriteFields(
               FALSE, [CliTable.Fields[Fld]]);
   end
   else begin
       // Data not found
       FResultStatus := 400;
       FResponseBuffer.WriteFields(
            FALSE, [Key, 'not found']);
   end;
   Finish;

end; </syntaxhighlight>