How to use system variables on the AS/400 from LANSA for Windows

Date:Archived
Product/Release:LANSA for Windows
Abstract:You can use any system variable on the AS/400 from LANSA for Windows when operating in a Client/Server environment
Submitted By:LANSA Technical Support

A LANSA application running on a PC is using data that is on an AS/400. The application has a requirement to use a system variable, for example *AUTONUMNXTORDNO - return the next available number for an order. If LANSA isn't told that this *AUTONUM system variable is to run on the server, it will assume that it is to run locally. This means that the number generated on different PCs could be the same! This would usually result in a data error on the server. So how is this avoided?

There are 2 methods:

  1. If the system variable is *AUTONUMxxxxx, *AUTOALPyyyyy or *DTALLLSSSzzzzz LANSA is automatically directed to route the request for the system variable to the server. To do this when using the Built In Function DEFINE_OS_400_SERVER specify to route the application requests for these system variables to the AS/400. This means that 2 people using separate PCs could run this application in SuperServer mode and they would both always get the next valid number.
  2. If the system variable is not one of the above and its necessary for it to be run on the server for some reason (for example the evaluating program is 3GL and cannot be moved to the PC or a system variable, equivalent to the ones mentioned above, has been defined by the user (even if it is in RDML) and therefore the system variable needs to be run centrally for application consistency) then there is another way. This technique involves writing a "wrapper" for the system variable or to include this "wrapper" code into your RDML system variable evaluation function.

Following are 3 examples of how to use your user defined (ie NOT the standard supplied system variables - handle those via the first technique defined above) *AUTOxxxxxxx system variables in a Client/Server environment.

Imagine an application has 3 system variables being used:

============================== 
Example 1 - A single allocator
==============================
Symbolic Name     Description                     
-------------     -----------
*AUTOCUSTNO Next   Customer Number          
*AUTOPRODNO Next   Product Number   
*AUTOBOLNO  Next   Bill of Lading Number          

When using LANSA for Windows "super server" to construct C/S applications the values could be assigned from a single function structured along the lines of this example (which is a function called GETAUTO):

function (*direct)
def_cond *onclient (*cputype *ne AS400)
case #autoname
when = CUSTNO
if *onclient
    exchange #custno
    use call_server_function (*server *function Y Y)
else
    change #custno *autocustno
endif
exchange #custno
when = PRODNO
if *onclient
    exchange #prodno
    use call_server_function (*server *function Y Y)
else
    change #prodno *autoprodno
endif
exchange #prodno
when = BOLNO
if *onclient
    exchange #bolno
    use call_server_function (*server *function Y Y)
else
    change #bolno *autobolno
endif
exchange #bolno
otherwise
abort 'Unknown request'
endcase
return

A function that wishes to assign, say, the next customer number would do the following:

change   #autoname CUSTNO                       
exchange #autoname                              
call     process(*direct) function(GETAUTO)     
<< #CUSTNO now contains the next customer number  >> 

Likewise, to allocate the next bill of lading number do as follows:

change   #autoname BOLNO                        
exchange #autoname                              
call     process(*direct) function(GETAUTO)     
<< #BOLNO now contains the next bill of lading number  >> 
Some points to note about this example :
  • The function GETAUTO is special. When it runs on the AS/400 server it allocates the "next" value from the *AUTOxxxxx variable and exchanges the result back to the caller. When it runs on the Client (PC) it calls itself on the AS/400 to allocate the "next" value before exchanging the result back to the caller.
  • The caller(s) of GETAUTO can run on the Client or the Server. No special logic is required.
  • It can of course be extended into many other situations.
    For example and any other user defined dynamic system variable could be handled this way.

Another more elegant way of solving this problem is to "wrapper" the *AUTOxxxxxx system variables inside user defined system variables.

If these system variable were defined:

=====================================
Example 2 - Using specific "wrappers"
=====================================
                                                  System
                                                  Variable
Symbolic Name        Description                  Evaluator
-------------        -----------                  ---------
*XAUTOCUSTNO         Next Customer Number         CCUSTNO
*XAUTOPRODNO         Next Product Number          CPRODNO
*XAUTOBOLNO          Next Bill of Lading Number   CBOLNO

and then coded the system variable evaluation routines CCUSTNO, CPRODNO and CBOLNO along these lines:

Function : CCUSTNO                              
--------                                        

function options(*num_system_variable)          
exchange #custno *always                        
def_cond *onclient (*cputype *ne AS400)  
if *onclient                                    
    use call_server_function (*server ACUSTNO N Y)
else                                            
    call process(*direct) function(ACUSTNO)     
endif                                           
change #sysvar$nv #custno                       
return 

Function : ACUSTNO                              
--------                                        

function *direct                                
exchange #custno *always                        
change #custno *AUTOCUSTNO                      
return

A function that wishes to assign, say, the next customer number would simply do the following (which is more or less identical to use the system variable *AUTOCUSTNO directy) .....

change   #custno *xautocustno                   

Some points to note about this example:

  • The functions wishing to allocate the "next" number use the name *XAUTO rather than the direct name *AUTO.
  • This solution creates a real system variable (*XAUTO) which can be used anywhere that a system variable can be used. For example if cond(*xautocustno = 1) or with_key(#company *xautocustno) are valid uses of the system variable within the RDML language.

This example is very similar to example 2, except that a generic interface to the system variable assignment is used.

If these system variables were defined:

==========================================
Example 3 - Using a more generic "wrapper"
==========================================
                                                 System
                                                 Variable
Symbolic Name        Description                 Evaluator 
-------------        -----------                 ---------   
*XAUTOCUSTNO         Next Customer Number        GETXNUM
*XAUTOPRODNO         Next Product Number         GETXNUM
*XAUTOBOLNO          Next Bill of Lading Number  GETXNUM

and then coded the system variable evaluation routine GETXNUM along these lines :

Function : GETXNUM                              
--------                                        

function options(*num_system_variable)          
def_cond *onclient (*cputype *ne AS400)         
define #evalfun *char 7 to_overlay(#sysvar$nm nn)
                 where nn is the appropriate position
if *onclient
    use call_server_function (*server #evalfun N Y)
else                                            
    call process(*direct) function(#evalfun)    
endif                                           
return                                          

Function : CUSTNO 
--------                                        

function *direct
exchange #sysvar$nv *always                     
change #sysvar$nv *AUTOCUSTNO                   
return                                          

Function : PRODNO                               
--------                                        

function *direct                                
exchange #sysvar$nv *always                     
change #sysvar$nv *AUTOPRODNO                   
return                                          

Function : BOLNO                                
--------                                        

function *direct                                
exchange #sysvar$nv *always                     
change #sysvar$nv *AUTOBOLNO                    
return                                          

A function that wishes to assign, say, the next customer number would simply do the following (which is more or less identical to use the system variable *AUTOCUSTNO directy) .....

change #custno *xautocustno

Some points to note about this example:

  • The functions wishing to allocate the "next" number use the name *XAUTO rather than the direct name *AUTO.
  • This solution creates a real system variable (*XAUTONUM) so it can be used anywhere that a system variable can be used. For example if cond(*xautocustno = 1) or with_key(#company *xautocustno) are valid uses of the system variable within the RDML language.
  • Function GETXNUM uses characters 12 to 18 of the system variable name to get the name of the "function" that should be called to evaluate the system variable. By using this approach only a single small function (like CUSTNO, PRODNO and BOLNO) needs to be written for each system variable. Function GETXNUM is generic and it will work for any *XAUTOnnxxxxxxx system variable program.