Dynamic Scope

Dynamic scoping makes it possible to determine the scope of an operation or trigger when instance names are not known, and to store only DSPs that have been modified.

When developing DSPs, including contained DSPs, you may not know the actual DSP instance names that will be available at runtime. In this case, dynamic scoping enables you to:

  • Package all database updates within a single transaction, preventing the possibility of data corruption
  • Block only selected data in multiple components
  • Minimize the amount data passed between client and server

Static Scoping Limitations

Assume that you have a DSP with several contained DSPs and you need to implement a store action that stores user modifications made in several of contained DSPs. To minimize the amount of data sent back to the server, only modified data should be stored, and to prevent possible data corruption from multiple store actions, all the data should be stored in one transaction.

If you know the names of all the contained component instances, you could declare the store operation of every contained DSP instance in the scope of the store operation of the container DSP. For example:

operation storeData
scope
 operation Instance1.store
 operation Instance2.store
 operation Instance3.store
endscope
...
end; storeData

However, this includes the data of all these components, regardless of whether it has been modified, and blocks the DSPs for the duration of the transaction.

If you implement the store action of the container DSP as a weboperation or webtrigger (which are client-side JavaScript actions). Using the JavaScript API, you could check all the contained DSPs for modifications, collect the modified DSPs in a list, and loop through the list to activate the store procedure of each DSP instance, one by one. However, this requires multiple transactions.

Dynamic Scoping

In a dynamic web application, components may be created in response to user choices, and each instance needs to be uniquely named. The available instances and their names are not known ahead of time, so they cannot be (statically) specified in the scope definition using operation InstanceName.OperationName.

Dynamic scoping is achieved by having the scope declaration call a client-side callback function that returns a list of DSP instances that can be used as the InstanceName specification. For example:

operation storeData
scope
  operation getInstances().store 
endscope
...
end; storeData

The callback function must meet the following requirements:

  • If the scope is declared for an operation or the exec operation, the callback function must be a weboperation. If it is for any other trigger, the callback function must be a webtrigger.
  • It must return an array of instance names.
  • Its JavaScript context must have the same scope as the operation or trigger, meaning that the JavaScript keyword this refers to the same DSP instance object (for an operation) or field object (for a trigger).

Note:  Nested callback is not supported. If an operation or trigger is itself a callback operation, any callback function declared in its scope block will be ignored at the runtime.

The callback function is executed by the Javascript API to determine the scope of the operation or trigger before it is executed. It does not modify the input or output scope—the operation or trigger in which the callback function is used will always be blocked by its callback function.

Dynamic Scoping

The following example implements a store routine for a DSP that has contained DSPs. For this example, assume:

  • The top-level DSP (MAIN_DSP) has:

    • A contained DSP called SUB_DSP. At runtime, multiple instances of SUB_DSP can be created on the client as a result of user choices.
    • A string field MODIFIED_INSTANCES.CONTROLS.DUMMY, which is used to a list of modified SUB_DSP instance names. The instance names are separated by a semi-colon (;)
    • A Save button (SAVE.CONTROLS.DUMMY) the implements a store routine, saving modified data from multiple component instances in a single transaction
    • A webtriggergetInstances, defined in the Extended Triggers
  • The contained DSP (SUB_DSP) has an operation storeData()
trigger detail ; of SAVE
public web
scope
   input                                       Callout 1
   output                                      Callout 2
   operation getInstances().storeData          Callout 3
endscope
variables
  string vInstList, vInstName
endvariables
  vInstList = $replace(MODIFIED_INSTANCES, 1, ";", ";", -1) Callout 4                                
  forlist vInstName in vInstList               
      newinstance "SUB_DSP", vInstName         Callout 5
      activate vInstName.storeData()           Callout 6
  endfor
end
  1.  Gather component data from the browser.
  2.  Return data from the server.
  3.  Include the scope of the store operations of the DSP instances returned by the getInstances callback function.
  4.  Convert semi-colon separated list to Uniface indexed List.
  5.  For each instance, ensure that the instance is created on the server. (This only needs to be done once. Subsequent requests only need to activate it.)
  6.  For each instance, activate its storeData operation.

Note:  The callback function getInstances() is implemented as a webtrigger because the store routine is implemented in a trigger (detail trigger of the SAVE field).

webtrigger getInstances
 javascript
   // create array of instance names
   var inst = this.getInstance();
   var ent = inst.getEntity("CONTROLS.MODEL");
   var occ = ent.getOccurrence(0);
   var lst = occ.getField("MODIFIED_INSTANCES");Callout 2.1
   var val = lst.getValue();                    
   var arr = !val ? [] : val.split(";");        Callout 2.2
   
   return arr;                                  Callout 2.3
                 
 endjavascript
end
  1.  Use the JavaScript API to get the MODIFIED_INSTANCES field object, starting from the current instance (this).
  2.  Convert the instance names separated by ; to a JavaScript array.
  3.  Return the names of the modified DSP instances as an array.

Related Topics